Zero-downtime migration is a compatibility protocol between application versions and database states.
Expand-Contract Migration
Zero-downtime migration is a compatibility protocol between deployed versions.
-- Deploy 1: expand
ALTER TABLE accounts ADD COLUMN display_name text;
-- Application dual-writes old_name and display_name.
-- Backfill in bounded, restartable batches.
UPDATE accounts SET display_name = old_name
WHERE id > $1 AND id <= $2 AND display_name IS NULL;
-- Deploy 2: read new column; validate; stop old writes.
-- Deploy 3: contract only after rollback window closes.Invariant: Every deployed application version remains compatible with the active schema.
Use when: You must rename or reshape a production column without a coordinated flag day.
Why this boundary matters
Old binaries, new binaries, backfills, and rollback may coexist. Removing compatibility before that overlap ends converts deployment into an outage.
Failure policy
| Boundary | Action |
|---|---|
| Old application version | Keep the old schema path compatible |
| Dual-write mismatch | Stop contraction and reconcile |
| Backfill running | Use bounded restartable batches |
| New read path fails | Retain a rollback-compatible fallback |
| Rollback window open | Do not remove the old column or contract |
| All versions migrated and validated | Contract in a later deployment |
Trade-offs
Expand-contract replaces risky downtime with temporary schema and application complexity. Dual writes can diverge, backfills consume capacity, and the safe sequence takes multiple deployments.
Decision rule: Use expand-contract when old and new application versions can overlap or rollback must remain possible.
Further reference
Browse all engineering snippets · Read the migration deep dive