advanced 3 min answer

A 20-year-old order management system must be replaced. It cannot be paused and its business rules are undocumented. What is your approach and what is the hardest part?

strangler-figlegacymigrationdatawalmart
Show the full answer Hide the answer

What is being tested

Whether you choose incremental replacement over a rewrite, and whether you know that the hard part is data rather than routing.

Why not a rewrite

Rewrites of long-lived systems fail for structural reasons rather than incompetence:

  • The requirements exist only in the code's behaviour, including behaviour nobody intended and some customer now depends on. There is no document to build from.
  • The business does not stop changing during the rewrite, so the new system chases a moving target and the old team must maintain both.
  • No value lands until the end, so the project is cancellable for its entire life and gets no corrective feedback.

The strangler approach

1. Insert the routing facade first, routing everything to legacy. A no-op release that proves the routing path, the observability, and the rollback. Highest-value first step and the one teams skip.

2. Choose the first slice for learnability. Real enough to prove the path end to end, small enough that being wrong is cheap. Often a read-only view or a peripheral capability.

3. Route on a business dimension — capability, geography, customer segment, product line — not a random percentage. Behaviour is then explicable and rollback is comprehensible to non-engineers.

4. Run both and compare. For read paths, send the request to both systems, serve the legacy result, and log every difference. This is the only reliable way to discover undocumented behaviour, and it will find dozens of cases. Budget time to triage them: some are legacy bugs you should not replicate, and deciding which is a business conversation.

5. Repeat, and decommission as you go.

The hardest part: data

Routing is easy. Data ownership is where these programmes stall. Three options, and you will use different ones for different slices:

Approach When Cost
Legacy remains system of record; new system reads via API or CDC Early slices New system inherits legacy latency and data model
Dual write Transitional The two will diverge; reconciliation is mandatory
Migrate data with the capability Mature slices Cleanest; needs synchronisation for anything still shared

The discipline is to state explicitly which applies to each slice. Letting it be decided implicitly is how you end up with three systems all believing they own the customer record.

The failure mode to plan against

The strangler that never finishes. The last 20% is the hardest — the rarely-used capabilities, the batch jobs, the reports, the integrations with partners who cannot change. Funding runs out, and the organisation now operates two systems permanently, which is strictly worse than either alone.

Guard against it by budgeting decommissioning explicitly as a deliverable, tracking "capabilities remaining on legacy" as the primary programme metric rather than "capabilities delivered on new", and being willing to accept an ugly compromise for the long tail — a thin emulation, or a negotiated retirement of a feature nobody uses.

What a strong answer adds

Naming the anti-corruption layer as a separate concern: while legacy remains the system of record, its model must not leak into the new services. One module translates; nothing beyond it knows the legacy shape. Without that, "replacing the mainframe" eventually means touching every new service, and the programme's second half costs more than its first.