Every CTO I meet who has lived through a "big bang" rewrite tells the same story with a slightly different scar. Eighteen months budgeted, thirty-one months delivered. The new system finally ships, and within a week someone discovers the old one still handled a tax edge case nobody documented in 2014. The rewrite that was supposed to free the business instead froze it for two years.
There is a better way, and it is not new. Martin Fowler named it after the strangler fig — a plant that grows around a host tree, branch by branch, until one day the original has quietly disappeared and the fig stands on its own. You modernize the same way: incrementally, in production, with the old system running the whole time.
Why the big bang keeps failing
The core problem with a full rewrite is not technical skill. It is that you are asked to reproduce years of accumulated business logic — much of it undocumented, some of it load-bearing — while the target keeps moving. The business does not pause for your rewrite. New regulations land, a competitor forces a feature, the old system gets patched, and now your "frozen" specification is already wrong.
There is also a brutal cash-flow reality. A big-bang rewrite delivers zero value until the day it goes live. You spend eighteen months burning budget and political capital before a single user notices a difference. If leadership changes or the market shifts before that day, the project dies half-built — and you are left maintaining two systems instead of one.
How the strangler fig actually works
Instead of replacing everything at once, you put a routing layer in front of the legacy system and peel off one capability at a time. Each slice moves to the new stack, gets validated in production, and starts carrying real traffic. The legacy monolith shrinks. Value ships continuously.
The mechanism is usually a façade or proxy — an API gateway, a reverse proxy, sometimes just a thin routing service — that sits between your clients and the old system. Requests it doesn't yet know how to handle pass straight through to the legacy backend. Requests for migrated capabilities go to the new service. Callers never know the difference.
The goal of any given month is not "the rewrite is done." It is "one more capability now lives in the new system, in production, and nothing broke."
A concrete sequence
- Instrument first. Put the façade in place and route 100% of traffic through it to the legacy system, changing nothing else. This alone de-risks everything that follows.
- Pick a leaf, not the trunk. Start with a bounded capability that has few dependencies — notifications, PDF generation, a reporting endpoint. Not the billing core.
- Run both, compare outputs. For critical paths, use a shadow or parallel-run pattern: send the request to both old and new, serve the old result, and log any divergence. You find the undocumented tax edge case before it hits a customer.
- Cut over gradually. Shift 1%, then 10%, then 50% of traffic with a feature flag. Roll back in seconds if the error rate moves.
- Delete the old code. This step is non-negotiable and always the one teams skip. If you never retire the legacy path, you have added complexity, not removed it.
Where it goes wrong
The pattern is not magic, and I've watched teams turn it into a mess. The most common failure is the strangler that never strangles: new capabilities get built, but nobody is funded to delete the old ones, so you run two systems indefinitely and pay double.
The second is shared database gravity. If the new service and the legacy monolith both read and write the same tables, you have not decoupled anything — you have just added a network hop. Untangling data ownership is the hard part of this work, harder than the code. Budget for it. Sometimes you need a period of dual-writes and a synchronization layer you fully intend to throw away.
The third is picking the trunk first. Teams get excited and target the scariest, most central module to prove the approach. Start there and your first migration is also your riskiest. Earn confidence on the edges.
Where to start on Monday
You don't need a transformation program or a new budget line to begin. This week, do three things. Draw the real dependency map of your monolith — not the architecture diagram from the wiki, the actual one. Put a proxy or gateway in front of it and route all traffic through it unchanged, so you have a seam to work at. Then pick the single most isolated capability you own and move just that one, end to end, including deleting the code it replaces.
Modernization is not an event you survive. It is a habit you build. The teams that win treat the legacy system as something they retire one honest slice at a time — and they never let the fig stop growing.
Look at your architecture today: what is the smallest thing you could safely strangle first?