The short answer
A full rewrite of a business-critical system is high risk because the existing system encodes years of undocumented edge cases that cannot be fully enumerated in advance. The strangler-fig pattern replaces functionality incrementally behind a routing layer, so the business keeps running and every step remains reversible.
Key takeaways
- Rewrites fail on undocumented behaviour, not on technology
- Strangler-fig means no freeze period and no all-or-nothing cutover
- Start with the highest-risk, lowest-coupling component
- Value arrives continuously rather than at the end
Every engineer who inherits a ten-year-old system wants to rewrite it. The instinct is understandable and the outcome is frequently poor — not because the new architecture is wrong, but because nobody can enumerate what the old system does.
The knowledge problem
A system that has run for a decade has absorbed thousands of small decisions: the special handling for one large customer, the rounding rule that matches a legacy finance system, the retry that exists because a supplier’s API is unreliable on Mondays. None of it is documented. Much of it is not known to anyone still employed.
A rewrite has to rediscover all of it, usually in production, usually via complaints.
The delivery problem
A rewrite delivers no value until it is finished. Meanwhile the old system still needs maintaining and regulatory changes still need implementing — in both codebases. Eighteen months in, when priorities shift, you have two systems and no migration.
Strangler fig
Named after the plant that grows around a host tree and eventually replaces it. You put a routing layer in front of the existing application and move one capability at a time behind it. Each move is small, independently testable and independently reversible.
How it runs in practice
- Put a proxy or gateway in front of the existing system. Nothing changes functionally; you now have a place to make routing decisions.
- Pick one capability — ideally high-risk and low-coupling. Build it in the new architecture.
- Route a small share of traffic to it, comparing outputs against the old path where you can.
- Increase the share. Keep the old path available until you are confident.
- Decommission the old code for that capability, and repeat.
Where to start
Usually with whatever is simultaneously highest-risk and lowest-coupling. An unsupported runtime, an authentication layer without MFA, a database past end of life. Those give you a security or cost win early, which funds the rest of the programme politically as well as financially.
What you should not start with is the most complex core domain. That is where undocumented behaviour concentrates, and you want the routing infrastructure and the team’s confidence established before you go near it.
When a rewrite is right
Occasionally it is. When the platform is genuinely unsupportable — a language runtime with no security patches, a vendor product that no longer exists. When the system is small enough that its behaviour genuinely can be enumerated. When the business process it encodes is being replaced anyway, so behavioural fidelity is not a requirement.
The honest test: can you write down everything the system does, and would a domain expert agree the list is complete? If not, you are not rewriting it — you are rediscovering it under deadline.