Most migration write-ups start at the cutover. The interesting part happens months earlier, in the unglamorous work of making two systems agree on what is true.
The shape of the problem
We ran two platforms that both believed they owned inventory: an older IIT system and the newer WMS. Both were live. Both had customers. The mandate was to consolidate them into one platform without a maintenance window the business could feel — this is US retail, and the Aug–Jan peak does not pause for engineering.
A migration is a reconciliation problem wearing a deployment costume.
Three rules that held up
- Dual-write before you dual-read. Long before traffic moved, we wrote to the new schema in the background and compared. The diffs are your real spec.
- Make the reconciliation job a first-class feature, not a script someone runs. It has a dashboard, alerts, and an owner.
- Ship the smallest module that proves the seam. For us that was Inventory Snapshot — high-traffic, easy to verify against the floor.
Server-side everything
The legacy UI paginated in the browser over tens of thousands of rows. The single highest-leverage change was moving pagination, filtering and sorting server-side, then redesigning the snapshot query around the access pattern instead of the table layout. High-traffic modules stopped timing out; the rest of the migration suddenly had room to breathe.
What peak season taught me
When you own P1/P2 stabilisation through a peak, you learn that reversibility beats cleverness. Every change shipped with a way back. The quiet weeks where nothing broke were the deliverable.