Rollback Plan
Work out how you would undo the change before you make it — and find out early when the honest answer is that you cannot.
When to reach for it
Before starting anything with a one-way door in it: a migration, a backfill, a deletion, a public API change, an integration that writes into someone else's system.
What changes
- You end with an undo written as commands and steps, in order, that someone who did not write the change could run at three in the morning without asking you.
- One-way steps are named up front — dropped columns, deleted rows, sent email, external side effects — and either made reversible or accepted on purpose.
- The trigger is decided while you are calm: the specific rate, symptom or clock at which you stop trying and go back.
- Time-to-undo is estimated against time-to-fix-forward, so you know which one you are actually choosing rather than defaulting into it.
- Reversibility problems surface while the design can still change — adding a column instead of altering one, soft delete instead of delete.
Pairs with
- Migration SafetyChange a schema or move data without ever creating a minute where the running code and the database disagree.
- Ship ChecklistThe last pass before a change goes out — what to verify, in the order that catches the most for the least time.
- Demo Then ShipProves the feature works in the actual running app, not only in the tests written for it.
Rollback Plan
Decide how this comes back out before you put it in. The plan is written by someone calm, for someone who is not.
1. Name the one-way parts
Go through the change and mark everything a code revert does not undo:
- Rows written, updated or deleted
- Columns, tables or files dropped
- Messages that leave the building: email, push, webhook, payment
- State changed inside a third-party system
- Caches or search indexes rebuilt in a new shape
- Anything another team has already started depending on
2. Write the undo as steps, not intentions
Exact commands, in order, with who runs them and what each one prints when it worked. Include how to tell it has finished. Write it for a reader who is tired, was not involved, and is doing this at three in the morning with someone waiting.
3. Set the trigger now
Choose the condition for pulling the handle before you are invested in the change succeeding: a specific error rate, a specific symptom, or a clock — "if it is not healthy twenty minutes after deploy, we go back". A trigger chosen mid-incident is chosen badly.
4. Time it
How long does the undo take, end to end? If undo is slower than fixing forward, then fixing forward is the plan, and it is far better to know that now than to discover it while the graph is red.
5. Ask what data does not survive going back
Records written by the new code in a shape the old code cannot read are the usual trap. Either make the previous version tolerate them, or write the cleanup query now and put it in the plan.
6. Redesign whatever has no undo
If a step cannot be reversed, change the design while changing it is still cheap: add rather than alter, soft delete rather than delete, write both rather than switch, keep the old path behind a switch for a stated number of days.
7. Attach it to the change
The plan lives with the thing it undoes — in the change description and the deploy notes — not in your head, and not in a chat thread that scrolls away by morning.
Rules
- Do not write "revert the commit" as the plan when the change wrote data. Reverting code does not un-write rows or un-send email.
- Do not depend on a backup nobody has ever restored from.
- Do not make the rollback require the thing that may be broken: the pipeline you just changed, the service that is down, the dashboard that is timing out.
- Do not skip this because the change is small. Size and reversibility have nothing to do with each other; one line can drop a table.
- Do not leave the trigger as "if it looks bad". It will look bad and fine at the same time, and the argument will eat the window.