The Strangler Fig
The legacy system retires one feature at a time — and there is never a cutover day to fear.
The incident
The rewrite was announced with a party and a deadline. Eighteen months later, the old system still ran the business, the new system ran the demos, and the business had changed enough that the new system's frozen requirements were already wrong. Two systems, double the maintenance, and a steering committee asking which one was real.
Why the obvious approach fails
Big-bang rewrites fail for a structural reason, not a talent reason: they demand the business stand still while the replacement catches up, and businesses don't stand still. Requirements drift, the legacy system keeps accumulating changes the rewrite must chase, and the cutover becomes an ever-receding cliff with all the risk concentrated on one day. The strangler pattern dissolves the cliff: a routing proxy sits in front, traffic peels off to modern services one capability at a time, and the legacy system shrinks in production rather than being replaced in theory. Every step ships value; every step is reversible; there is no day when everything must work.
The standard
- A routing facade fronts the legacy system from day one; every migration step is a routing change, and every routing change can be reversed.
- Capabilities migrate in value-and-risk order — highest-leverage, lowest-entanglement first — each with its own validation before traffic shifts.
- Old and new run in parallel per capability, with output comparison (via the Regression Net) before the legacy path is retired.
- The legacy system is never modified to accommodate the migration beyond the facade — its behavior is the reference, not a moving target.
- Progress is measured in production traffic served by the new system — not in code written.
How Cortex validates it
At plan time
modernization blueprints declare the capability decomposition, migration order, and per-step rollback route.
At validation
assert: each_migration_step.reversible == trueassert: capability_cutover.requires(parallel_parity_evidence)assert: legacy_modifications outside facade == 0Assertion syntax is illustrative.
At review
the approver sees, per step: the parity comparison, the traffic shift plan, and the rollback drill — before any routing changes.