Rebuilding a Dispatch Platform Without Downtime

When a client asks us to replace the system their entire operations team depends on, the brief is never really "rebuild this." It's "rebuild this, and if anyone notices, we've failed." That was the brief for Northwind's dispatch platform — a decade-old monolith that routed every driver assignment for a fleet running 24/7.
The constraint that shaped everything
There was no maintenance window. Dispatch doesn't pause for a deploy, and a failed cutover doesn't roll back cleanly when trucks are already mid-route. So the usual "freeze, migrate, flip the switch" plan was off the table before we wrote a line of code. Every decision after that followed from one rule: the old system keeps running until the new one has proven itself under real load, not staging load.
Running two systems in parallel
We used a strangler-fig approach: new routes went to the new service first, with a shadow write back to the legacy database so nothing downstream broke if we needed to retreat. Every write carried an idempotency key, because a retried request during a flaky deploy is a certainty, not an edge case.
// every write path ends here — makes a retried
// dispatch event a no-op instead of a duplicate
if (await seen(event.idempotencyKey)) return event.id
await commit(event)
That one guard removed an entire category of "why did this driver get assigned twice" incidents before they could happen.
- Mirror reads from the new service, compare against the legacy response, log every mismatch
- Once mismatches hit zero for two full weeks, start routing writes through the new service
- Keep the legacy write path alive as a cold fallback for one more release cycle
- Decommission only after a full billing cycle closed clean on the new system
The cutover nobody noticed
By the time we flipped dispatch fully onto the new platform, there was no cutover event to speak of — just a steadily rising percentage of traffic on the new service and a steadily falling one on the old. The dispatch team found out it had happened when we told them.
"We kept waiting for the day things would break. It never came. That was the whole point." — Northwind's Operations Director
What we'd do differently
We'd invest in the comparison-logging step even earlier. It caught three data-shape mismatches we hadn't planned for, and each one would have been a production incident if we'd cut over on faith instead of evidence.