Docs/Concepts/Migrations & versioning
OSS

Migrations and Versioning

A migration is a file. Its name says what kind it is and when it runs; its contents decide its checksum. Everything DBLift knows about your schema history follows from those two facts.

Kinds of script

The first character classifies the file, and it must be followed by a digit for the versioned kinds. That strictness is deliberate: it stops validate.sql or update.sql being mistaken for a migration.

PrefixExampleRuns
V{version}__V1_0_0__create_users.sqlOnce, in version order. The backbone of your history.
R__R__customer_dashboard_view.sqlEvery time its checksum changes. No version. Views, functions, grants.
U{version}__U1_0_0__drop_users.sqlOnly on undo, reversing the V file of the same version.
D{timestamp}__D20260618143022__fix_orphaned_orders.sqlData corrections — audited DML, ordered by timestamp rather than version. Addressed by id: dblift data undo D20260618143022. See Data Corrections.

R1__setup.sql — a versioned repeatable — is rejected. Repeatables carry no version.

Checksums

Every migration's contents hash to a CRC32 computed line by line, with line separators excluded — the same algorithm Flyway uses, and a signed 32-bit integer like a Java int, so a negative value is normal. Excluding line separators means checking the same file out on Windows and Linux does not change its checksum.

The checksum recorded at apply time is what makes an edited migration detectable. Change an applied file and validate reports drift; change a repeatable and the next migrate re-runs it. Same mechanism, opposite intent.

Order and selection

Versioned migrations apply in version order. Which ones are considered can be narrowed at the command line — by version, by tag, or by directory.

V1_0_0__create_users[core].sql
V1_1_0__users_created_at[core].sql
V1_2_0__add_note[auth].sql
dblift migrate --tags=auth --dry-run --show-sql
dblift migrate --exclude-tags=billing
dblift migrate --versions 1.1.0 --dry-run --show-sql
dblift migrate --target-version 1.1.0
dblift info --tags=auth
FlagEffect
--target-versionStop at a version instead of applying everything pending.
--tags, --exclude-tagsInclude or skip migrations carrying a tag, comma-separated. Matching is case-sensitive.
--versions, --exclude-versionsRun or skip an explicit list of versions.
--strictFail if a previously applied migration has gone missing, and require strict version order.

Tags live in the filename, in square brackets: V1_2_0__add_note[auth].sql. See Naming conventions. The same flags work on info, validate, undo and diff.

Out-of-order applies are visible after the fact too: the history table's installed_rank records the sequence rows were written, so a low rank on a high version is the fingerprint of a migration that arrived late.

SQL and Python migrations

The same naming rules apply to Python migrations — V1_0_0__create_users_container.py is a versioned migration like any other. Python is the only option on engines without SQL DDL: a .sql migration against Azure Cosmos DB or MongoDB fails with DBLIFT-NOSQL-001.

Python migrations are not linted by validate-sql

Policy packs read .sql files only, so a rule that blocks a dangerous statement in SQL will not see the same statement issued from Python.

See Naming Conventions for the full filename grammar and the callback events.

On this page