>
dbwarden
/ tool scope / repeatable migrations

Repeatable Database
Migrations.

Not every change is a one-time schema evolution. dbwarden supports three migration classes, so database objects that outlive a single deploy stay in the same reviewable workflow.

Versioned, runs-always, runs-on-change.

Versioned migrations (NNNN_) run once, in ordered version sequence: schema evolution, tables, columns, indexes, constraints. Runs-always migrations (RA__) run on every migrate execution, the class for objects that should always match the repository, views and grants. Runs-on-change migrations (ROC__) run when their content checksum changes, the class for routines and policies that should only reapply when they actually changed, functions, triggers, and policies.

At runtime, migrate builds one execution plan from file discovery plus migration metadata: pending versioned files first, then runs-always files, then runs-on-change files whose checksum differs from the last run, all under the same lock protection as the versioned sequence.

the three prefixes
NNNN_  runs once, in version order
RA__   refreshed on every migrate
ROC__  reapplied when the checksum changes
Which class should a function or trigger use?

Runs-on-change (ROC__). The routine is reapplied only when the file content changes, so unchanged objects are left alone.

How do repeatable migrations interact with the versioned sequence?

migrate builds the plan as pending versioned files first, then RA__ files, then changed ROC__ files, all under the same lock protection.

A view that stays current.

A runs-always migration re-creates the view on every migrate, so the definition never drifts from the repository, and a stale view cannot survive a deploy cycle. The file carries the same -- upgrade / -- rollback contract as a versioned migration, with the rollback beside the upgrade.

The ordering makes the class safe to use: because the plan applies pending versioned files before runs-always files, a view that references a column added in the same deploy picks it up in the same run, and can never be refreshed against a schema that does not yet have its objects.

You could generate the same file with make-migrations --type ra (or roc), so repeatables enter the workflow through the same generation path as versioned files instead of being hand-written in a separate system.

a runs-always view
-- primary__RA__refresh_active_users_view.sql
-- upgrade
CREATE OR REPLACE VIEW active_users AS
SELECT id, email FROM users WHERE is_active = TRUE;

-- rollback
DROP VIEW IF EXISTS active_users;
Which class should a view use?

Runs-always (RA__). The view is re-created on every migrate, so its definition is always whatever is in the repository, with no drift.

Can repeatable migrations be rolled back?

Yes. RA__ and ROC__ files carry the same upgrade and rollback sections as versioned migrations, with the rollback beside the upgrade.