part of a three-repo reference system

Zero-downtime migrations, measured.

Six schema changes against a real Postgres 16 with 200,000 orders, while a writer keeps hammering the table. Every step reports how long it took and how long the writer waited.

commit — postgres — generated —

How each scenario is judged

  1. Fresh database. Every scenario drops and recreates its own database, so a stale schema can never make a run look green.
  2. Fingerprint. The columns that must survive are checksummed before the change and compared afterwards. A checksum over a column that a scenario is supposed to change would prove nothing, so each scenario checksums what it promises to preserve.
  3. Backward compatibility. The previous release's query is executed while the schema is mid-expand. If it breaks, the scenario fails even if the new schema is fine.
  4. Writer latency. A loop updates a row every 50 ms for the whole run. The worst wait is compared with the scenario's budget. A migration that is fast but locks the table for two seconds is not a passing migration.
  5. Expected failure. Scenario 06 is bad on purpose and only counts as a pass when the harness catches it.

Results

Loading the last recorded run…

Why this is not a benchmark

The numbers are from one shared CI runner against 200k rows. They are good enough to show the shape of the problem — a blocking CREATE INDEX versus a concurrent one, a rewrite versus a shadow column — and useless as a prediction for your table. Run it against your own schema: PGURL=… ./scripts/run-lab.sh.

The patterns are not novel. They are the ones Postgres practitioners have written down for years; what is here is the harness that refuses to take them on faith.