Architecture & Technical Design · master area
Migration Design
Backward-compatible. Staged. Tested in staging. Reversible by default. The four rules every migration honours — designed at shaping time, not improvised at deploy time.
Owners: Tech Lead, Developer Phase it lives in: What We Build → How We Build The corpus principle this enacts: Rollback possible is not. A confirmed time is.
Where it lives in the chain
- How We Build · Migration discipline — the canon (four rules)
- What We Build · Sequence, Schema, API — where the migration's shape is first sketched
How to do this
The migration ADR names, before code begins:
- The destination schema — what the model looks like after.
- The bridge state — what both old and new code reads during the migration. Both versions must work, simultaneously, against the bridge.
- The deploy order — schema first or code first? Adding a column? Schema first. Removing a column? Code first.
- The backfill plan — how do existing rows get the new shape? Online (during read), offline (batch job), lazy (on next write).
- The cutover signal — what tells the team it's safe to remove the bridge? Usually a metric: zero reads of the deprecated field for N days.
- The reversal plan — if the cutover fails, what's the path back? Tested in staging.
What good practice looks like
A rename submitted_at → graded_at. Not a single migration. Five PRs:
- Add
graded_at, dual-write from now on. Backward-compatible. Reversible. - Backfill
graded_atfromsubmitted_atfor old rows. Idempotent. - Switch reads to
graded_at. Old code still works (writes both). Reversible. - Soak for two weeks. Watch the metric: zero reads of
submitted_at. - Drop
submitted_at. The point of no return — labelled explicitly.
A single PR that renames the column is an outage waiting to happen. The JWT outage shipped because the migration discipline wasn't applied to a config change. Configuration changes are migrations too.
Related crafts
- Schema Design — the destination
- Rollback Discipline — the verified path back
- Schema Migration (code) — the implementation