The platform handled every claim the business received. It also had no test environment, one developer who understood the batch jobs, and a release process that required an evening of downtime. Replacing it was not optional. Switching it off for a weekend was.
The constraint that shaped everything
Claims arrive continuously and have statutory response times. Any approach that required a freeze, a parallel run with manual reconciliation, or a big-bang cutover was ruled out in the first week. That left strangling the old system a capability at a time.
How it was sequenced
Read paths first
We put the new service in front of the old database for read-only operations: claim lookup, document retrieval, status. No writes, so no risk of divergence. This proved the new stack in production against real traffic before anything irreversible happened.
Then writes, one workflow at a time
Each workflow moved behind a feature flag with the old path kept warm. First notification of loss moved first because it was self-contained. Settlement moved last because it touched finance.
Batch jobs last, and rewritten rather than ported
The overnight jobs were the least understood part of the system. We reconstructed their behaviour from output comparison rather than from reading the code, running old and new in parallel for six weeks and diffing results until they matched exactly.
What made the difference
A shadow environment fed by production traffic, so defects surfaced before users met them.
Reversibility at every step. Every flag could be turned off in seconds, and several were.
Documenting the old system as a deliverable, not a side effect. That knowledge had been in one person's head.
Where it landed
Claim handling time fell by roughly a third, mostly from removing re-keying between screens. The migration completed without an unplanned outage. The team now releases during working hours.
This is the shape of most of our software development and infrastructure work. If you are carrying a system like this, let us take a look.
