Database Rollback Strategies

Rollback plans turn database migration failures from crises into routine procedures. Know your exit before you move forward.

By the SchemaSmith Team · Last reviewed

Rollback path for a failed database migration

Quick Summary

Every production database migration needs a rollback plan. The two main strategies are "fix forward" (deploy a corrective change) and "roll back" (revert to the previous state). Schema rollback is often straightforward because structure can be restored automatically. Data rollback requires planning because once data is transformed or deleted, it cannot be recovered without an explicit preservation script or backup. The best rollback strategy depends on whether your migration changed only schema, moved data, or both.

Why Rollback Planning Matters

Production migrations fail more often than teams expect. Constraint violations, lock timeouts, data conversion errors, and unexpected database state all cause deployments to not go as planned. Without a plan, a failed migration becomes an extended outage while the team figures out what to do next. Someone opens a query window, someone else checks the backup schedule, and a third person starts writing a reversal script from scratch. Meanwhile, the application is down or behaving unpredictably.

The time to plan your rollback is before you deploy, not during a 2 AM incident. A rollback plan answers one question in advance: "If this migration fails, what exactly do we do next?" Having that answer ready turns a potential crisis into a routine procedure.

Fix Forward vs Roll Back

There are two fundamental responses to a failed migration. Each has trade-offs that depend on the nature of the change.

Fix Forward

  • Deploy a corrective change that addresses the issue
  • Simpler when the migration partially succeeded (some data already transformed)
  • Works well for non-destructive changes (adding columns, indexes)
  • Risk: you are debugging and writing code under pressure during an incident

Roll Back

  • Revert to the exact prior state
  • Clean and predictable when possible
  • Can be automated with checkpointing or state-based tools
  • Risk: data written since the migration may be lost or incompatible

Rule of thumb

If the change was additive (adding things), fix forward. If the change was destructive (removing or renaming things), you need a rollback plan. Danilo Sato's Parallel Change writeup on Martin Fowler's bliki covers why additive-then-cleanup is the lower-risk shape for evolving live systems.

Schema Rollback vs Data Rollback

This is the critical distinction that most rollback discussions overlook. Pramod Sadalage and Martin Fowler make the same separation in their writing on Evolutionary Database Design: schema is reversible by definition; data transformations are not.

Schema Rollback safe

  • Reverting column additions, index changes, new tables
  • State-based tools can do this automatically (deploy previous state)
  • Low risk of data loss when changes were additive — the safe direction

Data Rollback dangerous

  • Reverting data transformations, column merges, data type conversions
  • Dangerous by nature: once data is transformed or deleted, you cannot "un-transform" it without a backup
  • Requires explicit planning: database snapshots, backup/restore, or preservation scripts

The hard truth

Most tools advertise "rollback support" but only handle schema rollback. Data rollback almost always requires manual planning. If your migration merges two columns into one, drops a table after migrating its data elsewhere, or changes a column's data type in a lossy way, no tool can automatically reverse that without a backup of the original data.

Practical Rollback Approaches

Different situations call for different rollback methods. Here is how the common approaches compare.

Approach Speed Data Safety Complexity Best For
State-based revert Fast Schema only (data may need manual handling) Low Schema-only changes
Down migration scripts Medium Depends on script quality High (must write and test) Changelog-based teams
Database snapshot/restore Slow Full data safety Low (but requires storage) Destructive changes
Point-in-time recovery Slow Full data safety Medium Catastrophic failures
Blue-green switch Fast Full data safety High (infrastructure cost) High-availability requirements

Vendor references: SQL Server database snapshots and point-in-time restore under the full recovery model; PostgreSQL backup and restore and continuous archiving and PITR; MySQL point-in-time (incremental) recovery.

Building a Rollback Checklist

Before every production migration, answer these six questions.

  1. What changed? Schema only, data only, or both?
  2. Is the change reversible? Can you drop the added column, or did you transform existing data?
  3. What is the rollback method? State revert, down script, snapshot restore, or fix forward?
  4. How long will rollback take? Seconds (state revert), minutes (down script), or hours (full restore)?
  5. What data is at risk? Any data written between migration and rollback could be affected.
  6. Who approves the rollback? Is there a decision-maker on call?

Writing these answers down before deployment takes five minutes. Figuring them out during an outage takes much longer, and the answers are usually worse.

How SchemaSmith Handles This

Rolling back means deploying the prior release's package. Because deployment is state-based — SchemaQuench compares the declared definition against what is live and generates only the difference — reverting is a matter of pointing it at an earlier definition rather than composing a reversal script. Most rollbacks need nothing more. The ones that do are the ones that touch data, and this procedure is ordered to surface those before anything runs.

1. Retrieve the prior release's package

Check out the tagged release from source control, or retrieve the schema package artifact kept from the earlier deployment. Tagging every release is what turns this step into a lookup instead of an archaeology exercise.

2. Preview it before you run it

WhatIf mode reports what the rollback would change and applies nothing:

SmithySettings_WhatIfONLY=true SchemaQuench

WhatIf is a human-facing preview — for reviewing the scope of a change, rehearsing a correction, or debugging a deployment before running it for real — so its value depends on someone actually reading the generated SQL. Two things to look for: tables that exist now but are absent from the older package, and columns being dropped.

3. Choose your drop posture, then deploy

DropTablesRemovedFromProduct defaults to true, so rolling back to an earlier package removes the tables the newer release added. That converges cleanly and destroys their data. Two postures are safe:

  • Set it false, so the rollback leaves those tables in place until you are confident the revert is permanent, then clean them up explicitly.
  • Keep auto-drops on and install the SchemaSmith.CustomTableDrop / SchemaSmith.CustomTableRestore recyclebin hooks, which move a removed table to a recoverable holding area instead of destroying it.

Neither posture covers columns. A dropped column is not caught by either mechanism, so preserve its data yourself — with a migration script — before a rollback that drops it. PreventDrop: true protects one specific table and is sticky, persisted in the database so the table is skipped even after it leaves the package entirely, but it protects tables, not columns.

Recovery is not undo

SchemaQuench records every completed step and migration script to disk as it runs. Re-running with --ResumeQuench skips what already finished and picks up at the first incomplete step; without that switch the resume logic is off and every step executes again. That is recovery — getting a stalled deployment over the line — not undo. A rollback is the separate, deliberate act of deploying an earlier package. Take a backup before a significant one, especially on MySQL and MariaDB, where the engine cannot unwind partial DDL on its own.

Frequently Asked Questions

Deploy the previous version of the schema package with SchemaQuench. It computes the delta from the current state back to that earlier version and makes only those changes. Deployments are idempotent, so the database converges on the declared state either way.

Not by itself. Rolling back reverts structure; schema state alone cannot recreate lost rows, and a dropped column's data is gone for good. A dropped table is recoverable only if you have installed the optional recyclebin hooks, which soft-drop it for a retention window instead of destroying it. If a rollback would remove data you need, plan for it separately: take a backup before the change, or use a migration script that moves the data somewhere safe before the original is dropped.

Check DropTablesRemovedFromProduct. It defaults to true, so rolling back to a package that no longer declares a table will drop it. In production many teams set it to false, leaving such tables in place until the rollback is confirmed permanent.

Hands-on lab

Practice rolling back by re-deploying the prior release's package, and add a data-preservation script when a change would otherwise drop data you need.

Start the recovery lab

Next Steps by Platform

Everything from here is organized by database. Choose yours below and keep going.

Shape. Strengthen. Succeed.

Free schema-as-code for SQL Server, PostgreSQL, MySQL, and MariaDB.

The source is on GitHub for anyone to read.

Get Started on GitHub