Skip to content

A small schema migration CLI

A single static binary that applies numbered SQL migrations to Postgres, checksums what it has applied, and takes an advisory lock so rolling deploys do not race.

Role
Author and maintainer
Client
Self-directed
Year
2025
Stack
CLIPostgresRust

A command line tool for applying SQL migrations to Postgres. It exists because I kept rewriting the same fifty lines of shell in every project, and because the off-the-shelf options either wanted a runtime I did not have or insisted on owning the schema.

Design

One directory of numbered .sql files, one table recording what has been applied, and a checksum on every applied file so an edited migration is an error rather than a surprise. There is no down-migration story: reversals are written as new files, which is what happens in practice anyway.

$ mig status --url "$DATABASE_URL"
  0001_init.sql             applied  2025-08-14T09:12:04Z
  0002_add_ledger.sql       applied  2025-08-21T17:40:11Z
  0003_backfill_totals.sql  pending
$ mig up --url "$DATABASE_URL"
  0003_backfill_totals.sql  applied in 812ms

Each migration runs inside a transaction, and the run as a whole holds a session advisory lock, so two instances starting at once during a rolling deploy is safe rather than a race. The binary is statically linked and around four megabytes, so it drops into a container image without dragging an interpreter along.

It is deliberately small and I intend to keep it that way. The interesting work in migrations is not the tool.

More work