How to replace a 15-year-old monolith while it keeps taking production traffic — without betting the company on a rewrite.
You've inherited a 15-year-old order-management monolith at a fictional logistics firm. It processes 40k orders a day, three of the original engineers are gone, and the test coverage is a rumor. Leadership wants it "modernized" by next year, and the loudest voice in the room is proposing a clean-slate rewrite.
That rewrite will fail. Not because the team is bad — because the legacy system encodes a decade of business rules nobody has written down, and a rewrite forces you to rediscover all of them at once, in production, on launch day. The strangler fig pattern rediscovers them one slice at a time, with a rollback lever in your hand. Here's the playbook.
Martin Fowler named this pattern after watching actual strangler fig vines on a trip to Queensland: the vine germinates in the canopy of a host tree, sends roots down around the trunk, and over years grows into its own self-sustaining structure as the original tree dies inside it. Swap "tree" for "monolith" and you have the whole strategy — the new system grows up around the old one, taking over piece by piece, until one day the host isn't load-bearing anymore. It's not a novel idea I'm pitching here; it's a well-worn technique documented in AWS's and Microsoft's own migration guidance, among others, precisely because it keeps working across very different stacks.
Click each stage. Every one of these is a shippable milestone with its own risks — treat them as gates, not a Gantt chart.
| Dimension | Strangler Fig | Big-Bang Rewrite |
|---|---|---|
| Risk exposure | Bounded per slice — a bad migration affects one route, rolled back in minutes. | Total at cutover — every undiscovered business rule fails on the same day. |
| Time to first value | Weeks — first new feature ships on the new stack while the monolith still runs. | 12–24 months — nothing ships until everything ships. Scope grows the whole time. |
| Team disruption | Sustained dual-system tax — you run two stacks for the whole migration. But no feature freeze. | Feature freeze — the business waits, then demands "just one thing" in the legacy system anyway. |
| Rollback-ability | Built in — the facade is a routing table; flip a percentage back to legacy. | Effectively none — rolling back a cutover after data has diverged is a second migration. |
If the legacy system still serves production traffic and you can't recite its business rules from documentation, you don't rewrite it — you strangle it. Big-bang is only for systems small enough to fully re-spec in under a quarter. This isn't a free lunch: you're trading a single catastrophic risk for a longer migration and a facade layer you now have to run — it's a better trade for most legacy systems, not a risk-free one.
The facade. Teams treat it as an nginx config and a Friday afternoon. It isn't. It owns authentication passthrough and consistent error semantics — production infrastructure with its own SLA.
It also owns translation, and that job has a name: an anti-corruption layer, a pattern Eric Evans defined in Domain-Driven Design for exactly this situation — two systems with incompatible models that still have to talk. Without one, calls pass straight through and the legacy system's quirks — denormalized tables, overloaded status codes, "status=3 has meant something different since 2019" logic — leak directly into your clean new domain model, and months of migration work end up recreating the same debt in new syntax. Worse, that leakage is exactly what makes stage 5 impossible: you can't retire a legacy system your new one has quietly come to depend on.
When the facade is flimsy, every migration slice becomes a firefight. Staff it like a real component: an owner, tests, observability, a one-line rollback path, and explicit translation logic at the boundary — not an assumption that old and new data shapes match. And be honest about the trade you're making — if the migration stalls (and they do stall, when priorities shift), that facade doesn't disappear. It becomes a permanent extra hop and a second system to maintain. A strangler fig that never finishes is just a new kind of legacy. In my experience, migrations that fail outright don't fail on the new services — they fail because the seam between old and new was treated as an afterthought instead of the thing the whole plan hinges on.
See the working example → A runnable facade-router POC that simulates the 0% → 100% traffic shift, by strangler-fig-migration-playbook on GitHub. Disagree with the playbook? Tell me where — I'd genuinely like to hear which stage broke for you.