Migration Flight Simulator — Change a Live Schema Without Downtime
A deterministic cockpit for the expand/migrate/contract pattern: old and new clients keep sending live reads and writes while one customer-name field becomes a normalized shape. Advance or roll back each stage, change the fleet mix and traffic, reorder non-atomic dual writes, stall the worker, break the target, and watch request errors, stale reads, replica mismatches, backfill lag, acknowledged-value loss, compatibility, and the destructive contract gate react.
What this is
A live schema-migration cockpit. Forty-eight records begin with one legacy full_name field while old v1 and new v2 clients continuously read and mutate them. You fly the system through additive expansion, non-atomic dual write, version-aware backfill, a normalized-first read cutover, an old-write fence, and final contract.
Every control changes the running model: client rollout, requests per minute, worker batch size, read order, write order, and three failure modes. Pause, single-step, roll a stage back, or run the seeded safe and rushed flight plans to compare the same migration discipline against the same kind of live traffic.
Why this is mind-blowing
The dangerous moment is not adding a column. It is believing that a populated column means the migration is safe.
This simulator tracks the last value each successful request actually acknowledged. That makes several failures visible at once: a request can return an error after its first write leg persisted, both shapes can be populated but disagree, a read can return 200 with stale data, and dropping the legacy field can erase the only live copy of an acknowledged value.
The order controls make the subtle failure concrete. If a non-atomic dual write persists the current read source first, a timeout before leg two can leak an unacknowledged mutation into successful reads. The safe flight writes the secondary representation first and the active read source last, then flips that order when normalized reads become primary. The rushed flight keeps the dangerous order and injects the timeout.
Then it tries to contract. The simulator does not reward forward motion: it refuses the destructive change, identifies the rows that would be lost, points to the old clients still in flight, reports the incomplete soak and active fault, and leaves the system inspectable. Zero downtime is not a brave click. It is a proof that the old shape has become irrelevant.
Prompt
Build “Migration Flight Simulator — Change a Live Schema Without Downtime,” a polished, accurate, single-file expand/migrate/contract simulation. Simulate live traffic from old and new clients over records moving from a legacy field to a new normalized shape. Users advance or roll back explicit stages (expand schema, dual write, backfill, switch reads, stop old writes, contract), adjust old/new client mix and traffic, inject a failure, pause/step/play, and run deterministic safe/rushed presets. Track requests, error rate, stale/mismatched records, backfill lag, data-loss/invariant checks, and compatibility matrix. Prevent unsafe contract or clearly fail it with an explanation. Demonstrate why dual-write/read order matters. Responsive 390px, accessible keyboard/touch, reduced motion. One inline HTML/CSS/JS file, no external resources/network/build, <=160KB.
Paste into your favorite AI and adapt it to your context.
What I learned shipping it
- Why expand/migrate/contract is a compatibility protocol rather than a sequence of DDL statements: the safe contract condition is about every live reader, writer, and acknowledged row, not whether the replacement columns exist
- How non-atomic dual-write order interacts with read preference: writing the primary read source first can expose a mutation from a request that ultimately failed, while writing it last contains the partial result on the secondary path
- Why backfill completion, replica equality, stale-read rate, live-copy loss, and client compatibility are separate signals, and why a destructive migration gate must evaluate all of them