An agent ships the forward migration and forgets the way back
An agent writes the forward migration, it applies cleanly on the branch, and the PR body reads 'schema updated.' What it leaves out: how the change reverses, what happens to existing rows, and how you prove a read after the write still works. A migration that only runs one direction is a draft, not a finished change.
A forward-applied migration is not a done migration
The green checks that cover the code branch usually run against an empty or seeded development database, so 'applies cleanly' proves almost nothing about production. A column added, a type widened, a value moved from one field to another: the forward path is one line in the migration file. The operational risk lives in what the forward file cannot show, which is old rows, partial deployments, and the moment you need to back out.
The three missing pieces
- A rollback that runs. The down migration must be tested, not just written. A column-drop rollback that forgets to restore the moved data is worse than no rollback, because it sounds reversible while destroying the record.
- A backfill for existing rows. New columns filled by a default on new writes leave old rows stale. The backfill window, batch size, and lock behavior belong in the PR, not discovered at 2 a.m.
- A read-after-write check. After the change, prove a write lands where expected and a read returns it, against the same shape production uses. This catches the half-migrated state where some rows carry the new value and others still carry the old one.
Make the agent list both directions before coding
Give the task a fixed block: forward steps, reverse steps, backfill strategy, and the check that proves success. The agent tends to write forward because that is the requested feature; asking for the down path up front forces it to consider what it is moving before it destroys the original location. If the rollback cannot preserve data, that limitation belongs in the PR rather than hiding behind 'no rollback needed.'
The cheap reviewer check
Before merging, ask two things: what command reverses this, and what happens to a row written before the deploy. If the agent cannot answer both without inventing them on the spot, the change was planned as a one-way trip. Reversible or not, the PR should state the assumption and the fallback plainly.
When the changed column also feeds an API response field, keep the contract spec moving with the migration instead of letting the backend drift ahead of the documented shape. That local-first spec workflow is what we built into Powerduck, where the spec stays the source of truth rather than a stale markdown note nobody reopens.
Done for a migration means the operator can apply, reverse, fill, and verify. It does not mean the forward file exists.