A team deploys several times a day and needs to change a database schema. What sequence prevents downtime, and which step is skipped?
Show the full answer Hide the answer
The sequence
Expand, migrate, contract, across several deployments:
- Add the new column or table. Nothing reads it; both application versions work.
- Deploy a version that writes both shapes and reads the old.
- Backfill in batches, without locking.
- Deploy a version that reads the new shape and still writes both.
- Deploy a version that writes only the new shape.
- Remove the old column.
Each step is independently deployable and reversible, and at no point do the running application versions disagree with the schema.
Why the sequence is necessary at all
A rolling deployment means two application versions run simultaneously by design. Every migration step must be compatible with both, and teams that think of deployment as atomic get this wrong repeatedly — deploying a version that reads the new shape before the backfill completes, or removing a column while a previous version is still running somewhere.
What makes the backfill safe
Batched with a bounded rate, so it does not saturate the database or cause replication lag · resumable, since it will be interrupted · idempotent, since it will re-process rows · monitored for its effect on production latency with the ability to pause, because a backfill degrading the live workload is a self-inflicted incident and during a billing run it is a serious one.
The step that is skipped
Contract. Removing the old column requires proving nothing reads it — work with no visible benefit — so it is deferred indefinitely. The result is a schema accumulating columns nobody dares remove, and the next migration is harder because the picture is unclear.
The fix is to schedule the contraction with an owner and a date at the time the expansion is planned, not afterwards.
The automation that makes this sustainable
Migrations as part of the pipeline with a check that fails the build on a backwards-incompatible change. Detecting a dropped column or a narrowed type automatically is straightforward, and it converts a discipline that depends on remembering into a control that does not.