11 min readpostgresmigrations
Migrations you can stop halfway
A migration that cannot be abandoned at any point is not a migration, it is a commitment ceremony with a deploy button.
A migration that cannot be abandoned at any point is not a migration. It is a commitment ceremony with a deploy button, and the only rollback plan is the one you improvise while the graph is red.
Expand, migrate, contract — and mean it
Everyone knows the three phases. Fewer teams treat the gaps between them as places you are allowed to live for a month. That is the whole point: each phase leaves the system in a state that is correct, deployable, and revertible on its own.
Backfills are jobs, not scripts
A backfill run from a laptop is a single point of failure wearing a hoodie. Make it a job with a cursor, an idempotent batch, and a stop switch. You will need to pause it during an unrelated incident, and you should be able to do that without losing your place.
Dual-write is a trap unless you dual-read
Writing to both places feels like safety. It is only safety if something is continuously comparing the two and telling you when they diverge. Without that reader you have doubled your write path and learned nothing.
The contract phase is the one people skip
Dropping the old column is unglamorous and slightly frightening, so it sits in a backlog until the shape of the table is a fossil record of every migration nobody finished. Schedule it in the same quarter or accept that it will not happen.