arrow_back All posts
A Migration Failed Midway. Now What?
database migration failedschema rollbacksql recoverydeployment incidents

A Migration Failed Midway. Now What?

Half-applied schema changes are the scariest database state. Here's how to diagnose, recover, and prevent the next one.

Yuki Tanaka · Platform Engineer · September 16, 2026 · 4 min read

Of all deployment failures, a migration dying partway through carries unique dread: the schema is now half-old, half-new, the application may not start, and your instinct screams "run something else immediately." Resist that instinct for ten minutes. Failed migrations follow a small set of recoverable patterns, and the difference between a five-minute fix and a lost weekend is almost always whether diagnosis preceded action.

Step zero: stop and photograph the scene

Before any repair attempt, capture current state exactly: what the migration tool believes happened (its versions or changelog table), what the schema actually looks like (which new tables or columns exist), and the complete error from the failed run. Screenshot or copy all three somewhere safe. This sounds bureaucratic until you're three attempted fixes deep with no memory of original state — at which point this record becomes the only reliable map. Agents asked to help will request exactly this information anyway; having it ready turns their first response into a solution instead of questions.

A Migration Failed Midway. Now What?

Connect the Claude or Codex you already pay for — the rest runs on workers that cost a fraction.

Download meshcode →

Understand which of the three failures you have

Mid-migration failures sort into three types. Type one: the change applied but the tool crashed afterward — schema is actually correct, only the bookkeeping row is missing; the fix is marking it applied. Type two: partial application within a single migration — some statements ran, later ones failed; you must manually finish or reverse the remainder. Type three: applied cleanly but broke the application — schema and records agree, yet code assumptions were wrong; here rollback is a choice, not an emergency. Diagnosing type first prevents the classic blunder of re-running migrations against schemas that already changed.

The transaction question determines everything

Databases differ crucially on whether schema changes roll back atomically when a migration fails. Systems supporting transactional DDL make type-two failures nearly vanish — failure restores the pre-migration state automatically, leaving only bookkeeping to reconcile. Others apply each statement immediately, meaning partial states persist and manual cleanup is real work. Knowing which behavior yours exhibits tells you whether that half-created table you're staring at should exist. If unsure, ask your agent to explain your specific engine's DDL transaction semantics — a two-minute answer preventing an hour of wrong guesses.

Manual recovery, done carefully

When cleanup is needed, write it as explicit SQL reviewed like production code, because it is production code: drop or alter exactly the objects the failed migration created, verify each statement's target exists before touching it, and test the whole script against a restored copy first whenever possible. Then re-run the original migration from clean state rather than hand-finishing its remainder — letting the tool do its job keeps history coherent. The discipline mirrors broader backup and rollback safety practice: rehearse recovery on copies so production execution is boring.

If you must roll back the application too

Sometimes forward recovery waits for proper fixes and the priority is restoring service: redeploy the previous application version against the partially migrated schema. Whether old code tolerates new columns depends on change direction — additive changes (new nullable columns, new tables) usually coexist harmlessly with older code, while renames and type changes don't. This asymmetry is why the additive-only habit dominates advice for keeping AI agents from breaking existing systems: forward-compatible migrations make every failure mode gentler.

Prevention beats heroics every time

Four habits eliminate most recurrence. Small migrations: one logical change per file means failures are surgical, never sprawling. Tested migrations: run against production-shaped data before production — realistic volume surfaces timeout failures that empty dev databases hide. Backups immediately before risky runs: verified, restorable snapshots turn worst cases into inconveniences. And explicit down-paths written while context is fresh, even if you hope never to use them. Teams using AI-generated migrations should add a fifth: human review of generated SQL, applying the same scrutiny as any AI-written code before shipping.

Writing the post-mortem that matters

After recovery, spend fifteen minutes writing what happened while details remain: timeline, root cause, detection lag, what made recovery easy or hard. The value isn't documentation ritual — it's noticing patterns across incidents. If migrations fail during deploys, the deploy process needs a pre-flight step. If failures cluster around large tables, locking strategy needs revisiting. Individual incidents look random; three post-mortems reveal your system's actual weak points faster than any dashboard.

The meshcode angle

Migration recovery means reading error output, inspecting schema state, and crafting careful SQL — iterative diagnostic work where an agent proposes fixes in one pane while you verify each against the live database beside it. meshcode keeps those loops tight and every diff reviewable. Bring your existing Claude Code or Codex subscription or use metered pay-as-you-go credits.

👉 Download meshcode — Mac, Windows