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.