A travel platform must migrate a large legacy booking system to cloud services without a big-bang cutover. Design the migration using a strangler approach, and identify what makes data the hard part.
Show the full answer Hide the answer
The migration structure
1. Put a façade in front of the legacy system first. All traffic routes through a proxy that can direct each request to either the legacy system or a new service. Nothing changes functionally; this step exists purely to create the switch. Doing it first is what makes everything afterwards incremental.
2. Choose the first slice by risk and independence, not by importance. A capability with few dependencies, clear boundaries and modest traffic — often a read-only path such as search or content retrieval. The purpose of the first slice is to prove the migration machinery, not to deliver value.
3. An anti-corruption layer at the boundary. New services must not inherit legacy data models and naming. Translation happens explicitly at the seam, or the "new" system becomes a distributed copy of the old one with extra network calls — the most common way strangler migrations fail.
4. Traffic shadowing before switching. Send real traffic to both systems, serve the legacy response, and compare. This finds behavioural differences that no test suite will, particularly the undocumented edge cases that turn out to be load-bearing business rules.
5. Incremental cutover with instant rollback. Move a percentage of traffic, watch business metrics rather than just technical ones, and keep the ability to revert with a configuration change.
6. Decommission deliberately. A slice is not migrated until the legacy path is removed. Otherwise the organisation operates both forever and pays for both, which is the most common outcome of migrations that lack an explicit removal step.
Why data is the hard part
Traffic routing is a solved problem. Data is where migrations actually fail.
Both systems need the data during the transition. Options, none free:
- Legacy remains the system of record, new services read from it or from a replica. Simple and safe, but the new services are not independent and the migration cannot complete.
- Bidirectional synchronisation. Both write, changes propagate both ways. Maximum flexibility and maximum danger: conflicting concurrent writes, loops, and drift that is invisible until reconciliation.
- Migrate ownership per entity. Each entity type has one system of record at a time, moved deliberately. Most complex to orchestrate, and the only approach that reliably reaches an end state.
Reconciliation is mandatory, not optional. Continuous comparison of the two datasets with alerting on divergence — because in any dual-write arrangement, drift is a certainty and the only question is whether you detect it or a customer does.
The legacy schema is usually wrong for the new system, so migration involves transformation, which means the mapping needs its own tests and its own rollback story.
The failure mode that kills these programmes
Perpetual coexistence. Two systems, a synchronisation layer, and no slice fully removed. The organisation now operates three things instead of one, forever, and the business case evaporates.
The counter is to make decommissioning a first-class deliverable with a date and an owner for every slice, and to treat "the legacy path still exists" as an incomplete migration rather than as a completed one with a small remainder.