schema-migrationslisted
Install: claude install-skill Markuysa/agent-skills
# Schema migrations
The dangerous property of a migration is that **old and new application code run
at the same time** during a deploy — and again, in reverse, during a rollback.
Every migration must be safe for both versions, or the deploy window becomes an
outage window.
The second dangerous property: a lock held for 200ms in staging can be held for
minutes in production, behind a long-running query, while every request queues
behind it.
## Expand / contract
Never change a schema in one step. Split every breaking change into deploys that
are each individually safe:
1. **Expand** — add the new structure. Nullable or defaulted, no reads yet.
2. **Dual-write** — new code writes both old and new. Deploy it.
3. **Backfill** — fill the new structure for existing rows, in batches.
4. **Migrate reads** — new code reads the new structure. Deploy, verify.
5. **Contract** — stop writing the old, then drop it. Days later, not minutes.
Each step is independently deployable and independently revertible. The gap
between step 4 and step 5 is deliberate: it is your rollback window, and closing
it early is how a bad deploy becomes unrecoverable.
**Renaming a column is not an operation** — it is this entire sequence. A direct
`RENAME` breaks every running instance of the old code the instant it commits.
## Locks: know what blocks
Engine-specific; these are Postgres, and the exact list shifts by version — check
your version's docs before assuming.
| Operation | Blocking? |
| --- | -