Cards/DatabasesSystem Design · Day 45Sep 16, 2026

Never Change Anything in One Step

A column rename breaking during a rolling deploy while both code versions are live, and the expand-migrate-contract sequence that makes each step safe alone and reversible

A column needs renaming. The migration runs, the deploy follows, and for ninety seconds both versions of the code are live — old pods reading the old name, new pods writing the new one. Errors in production, for a rename.

Nothing here is a database problem. It's a timing problem: schema and code never change at the same instant.

The safe way is three steps. Expand — add the new column, nothing reads it yet, old code untouched. Migrate — write to both, backfill the old rows in batches, then move reads across one deploy at a time. Contract — once nothing references the old column, and only then, drop it.

Every step is safe on its own and every step is reversible. The temptation is speed: contract feels like it can follow migrate immediately, and it can't, because somewhere a pod is still running last week's code.

When two things can't change together, the answer is a period where both are true.

When two things can't change together, the answer is a period where both are true.