module-27/zero-downtime-migrator.mdDELIVERY STANDARD

The Zero-Downtime Migrator

The schema changes. Production doesn't notice.

The schema migration locked the orders table for eleven minutes — in a system that had promised the business zero downtime.
The migration sequence that never locks production: expand-then-contract schema changes, dual writes, asynchronous backfill, verified parity, then cutover — every step reversible.

The incident

The migration was one line: add a NOT NULL column with a default. On the staging database it took a second. On the production orders table — two hundred million rows — it took an exclusive lock and eleven minutes, during which every order in the company queued behind an ALTER TABLE. The system that had promised zero downtime delivered eleven minutes of it, from one line everyone had approved.

Why the obvious approach fails

Schema changes that are instant on small tables can be lock-holding sieges on large ones — and the difference is invisible in every environment except the one that matters. The deeper trap is coupling: changing the schema and the code in one step means there's a moment when they must match exactly, and deploys aren't instantaneous across a fleet. Live migration is a choreography problem: expand the schema first (additive, non-locking), migrate data asynchronously in batches, run dual writes while both shapes coexist, verify parity, shift reads, and only then contract — with every step independently deployable and independently reversible.

The standard

  • Migrations follow expand-then-contract: additive changes first, destructive changes last, and never in the same release as the code that depends on them.
  • Large-table operations are lock-audited before they run: anything taking more than a declared lock budget must run as an online/batched operation.
  • Data backfills run asynchronously in bounded batches with progress tracking — never as one transaction holding one lock.
  • Dual-write windows keep old and new shapes consistent during transition, with parity verification before reads shift.
  • Every migration ships with its reverse; 'roll forward only' requires explicit sign-off, not habit.

How Cortex validates it

At plan time

every schema change in a Mission declares its expand/contract phases, lock analysis, and reversal path.

At validation

assert: migration.lock_time < budget on production-scale dataassert: destructive_change.release != dependent_code.releaseassert: dual_write_window → parity_verified before read_shift

Assertion syntax is illustrative.

At review

the approver sees the rehearsal: the migration run against a production-scale replica, lock times measured, parity proven, reversal tested.

Composes with

See where your codebase stands against this standard.