The strangler fig pattern legacy software approach is the most reliable way we know to replace a system your business depends on without stopping the business to do it. Instead of switching everything over on one terrifying weekend, you grow a new system around the old one, move one piece of functionality at a time, and retire the old code only when nothing depends on it any more. This article will help you judge whether the pattern fits your situation, plan a first slice that proves the approach, and avoid the traps that turn a careful migration into two systems you must maintain forever.
This is written for owners, operations managers, and technical leads rather than for architects. You do not need the jargon, but you do need an honest picture of how tangled your current system is.
What the strangler fig pattern actually is
The name comes from Martin Fowler, who described the pattern in 2004 after watching strangler figs grow around host trees: the fig starts in the canopy, sends roots down around the trunk, and eventually stands on its own in the shape of the tree it replaced. The software version works the same way. You place a facade, usually a reverse proxy or API gateway, in front of the legacy system. Clients keep calling the same addresses they always called, and the facade decides, request by request, whether the old system or a new service answers. Early on, almost everything still goes to the legacy system; over time, more routes point at new services, until the old system serves nothing and can be switched off.
Three things make this different from an ordinary rewrite. First, value arrives with the first migrated feature. Second, every step is reversible: if a new service misbehaves, you flip its route back to the legacy system. Third, the business never stops: no freeze weekend where nobody can place orders while IT performs surgery.
Why the big-bang rewrite keeps failing
Most teams do not choose a big-bang rewrite because they love risk. They choose it because the legacy system has become embarrassing, the new design looks clean on a whiteboard, and starting fresh feels faster than untangling the old code. Then reality arrives. A rewrite scoped at six months takes far longer, because the old system contains years of undocumented business rules that only surface when someone tries to reproduce them. The business changes underneath the project, and every change has to be built twice. And all the risk concentrates into a single cutover event, where every misunderstanding becomes a live incident at the same time.
None of this means rewriting is always wrong. We have written before about the rebuild versus refactor decision, and the same logic applies here: a small system with few users, or a codebase so small that a rewrite genuinely takes weeks, can be replaced in one go without drama. The strangler pattern earns its keep when the system is large, live, and load-bearing. If your system can be down for a weekend without anyone noticing, you do not need this pattern. If it cannot, you probably do.
Strangler fig pattern legacy software: the five-stage migration
1. Find the seams before you write any new code
A seam is a boundary where one part of the system can be separated from the rest without dragging everything with it. Good first seams are features with clear inputs and outputs: reporting, notifications, a customer portal page, an import routine. Bad first slices are the tangled core: pricing, payments, or anything where five modules share one database table and nobody can say which one owns it. Ask daily users, not just developers, which workflows are actually one job.
2. Build the facade and prove it is invisible
The facade sits in front of the legacy system and routes requests. At first it routes everything to the old system, and its only job is to prove it changes nothing: same responses, same behaviour under load. This step feels like wasted effort and it is the step teams most often skip. Skipping it is a mistake, because once the facade starts routing, you need to be certain that any difference you see comes from the new service, not from the routing layer. Treat the facade as production infrastructure from day one, with its own monitoring, because it will eventually carry every request your business handles.
3. Build one slice properly, not five slices quickly
Build the chosen slice as a genuinely finished piece of software: its own tests, deployment, and monitoring. Where it needs data the legacy system owns, put an anti-corruption layer between them, a small translation component that stops legacy data shapes and quirks from leaking into the new design. Without it, the new service quietly inherits the old system’s compromises. Do not start a second slice before the first is live and stable.
4. Route traffic gradually, with the rollback agreed in advance
Move traffic in stages: internal users first, then a small percentage of real traffic, then all of it, watching error rates and business outcomes at each stage. Where it matters, run the new service in shadow mode first, sending it copies of real requests and comparing its answers with the legacy system’s before any customer sees them. Agree the rollback criteria before you start routing, not during an incident: which metrics, which threshold, and who can flip the route back. A rollback that needs a meeting is not a rollback plan.
5. Retire the old code, and mean it
Retirement is a scheduled activity with an owner and a date. Keep the old code for a defined retention window after its traffic reaches zero, long enough to cover month-end or quarter-end, then delete it and remove its routes. Every unretired slice is a system you still patch, still secure, and still explain to new hires. Migrations that never retire anything do not reduce complexity; they add a second system to the first and call it progress.

Data is the hard part, not the code
New services are the easy half of a strangler migration. Data is where migrations stall, because old and new systems usually need the same facts at the same time. You can let both share the legacy database, which is fast to start but keeps the legacy data model in charge of everything. You can split the data, giving each slice its own store and synchronising changes, which is cleaner long term but introduces sync lag and reconciliation jobs. Or you can move an entity’s data wholesale when its slice migrates, which is cleanest but demands a careful one-time migration and a fallback.
Whatever you choose, keep one rule absolute: one system of record per entity at a time. The moment two systems both believe they own the customer record or the invoice state, you have built a reconciliation problem costlier than the migration itself. Make ownership transfers explicit, and run a daily reconciliation report during coexistence. Also plan for transactions spanning the boundary: a workflow updating both a migrated slice and a legacy module can no longer rely on a single database transaction, so it needs compensating steps if the second half fails.
From our experience: where strangler migrations go wrong
Having worked on legacy systems across web, mobile, and custom software for over nine years and more than 300 projects, we have seen the same failure modes repeat. The first is the facade that becomes permanent: the routing layer was meant to be scaffolding, but nobody scheduled its removal, so years later the business runs on a legacy system, a new system, and a routing layer everyone is afraid to touch. The second is the oversized first slice. Picking payments or pricing as the pilot concentrates the hardest data problems and the highest blast radius into the moment the team has the least experience with the pattern. Start boring, and prove the machinery on something that matters but will not end the company if it wobbles.
The third failure mode is feature work continuing on the legacy system during the migration with no plan for it. Every new legacy feature is a slice that now has to be migrated twice. Either freeze new legacy development except for emergencies, or staff the mirroring work explicitly. The fourth is underestimating dual-running cost: two systems mean two sets of monitoring, patching, and security surfaces. Budget for that honestly, because a migration sold as cheaper than a rewrite loses trust when its real costs appear.
Finally, know when not to strangle. If the system is small enough to rewrite in weeks, rewrite it. If the honest answer is a bought-in platform, do that and use the facade only as a cutover aid. If the legacy system has no seams at all, because everything shares one database and one tangled codebase, then the first job is carving seams, which is refactoring work, not strangling. And if the team cannot sustain parallel running, a strangler migration will make the workload worse before it makes it better, and that conversation needs to happen before the project starts, not three months in.
What a realistic plan looks like
A realistic plan starts with a short discovery phase: map the seams, identify data ownership for each candidate slice, and pick a pilot that is valuable, separable, and reversible. Then build the facade and prove it invisible. Then deliver the pilot slice end to end, including retiring the corresponding legacy code, and review what the cycle actually cost. Only then commit to a cadence for the remaining slices, with a retirement gate for each one: zero traffic, retention window passed, routes removed, code deleted. Name three owners: one for the facade, one for parity checks between old and new, and one with the authority to halt a slice.
Expect the migration to take months, not weekends, and to feel slower than a rewrite at first. That is the point: risk paid in instalments instead of all at once, while the business keeps trading. If you need help scoping this for your own system, our custom software and API development team does this kind of legacy assessment, seam mapping, and staged replacement for businesses that cannot afford to stop.
Frequently asked questions
How long does a strangler fig migration take?
Think in months, not weeks, for anything load-bearing. The pilot is slowest because it includes building the facade; later slices get faster. Time the pilot properly and extrapolate.
Do we need microservices to use the strangler fig pattern?
No. The pattern describes how you migrate, not what you migrate to. The destination can be a set of services, a well-structured modular application, or a bought-in platform sitting behind your facade.
What happens to the data while both systems run?
Both systems need the same facts, so you either share the legacy database, synchronise copies, or move an entity’s data when its slice migrates. Whichever you choose, keep one system of record per entity at a time and run a daily reconciliation report during coexistence.
Can we roll back a migrated slice?
Yes, and that is one of the pattern’s main advantages. Because the facade routes traffic, rolling back means pointing the route back at the legacy system. Agree the rollback metrics and decision-maker before you start routing traffic.
When should we not use the strangler fig pattern?
Skip it when the system is small enough to rewrite quickly, when the right answer is a bought-in replacement, when the legacy system has no separable seams, or when the team cannot sustain running two systems in parallel.
The strangler fig pattern is not glamorous, and that is its virtue. It trades the excitement of a grand rewrite for a boring, repeatable cycle: find a seam, build a slice, route the traffic, retire the old code. Businesses that follow it end up with a new system they understand and no weekend where everything depended on a single cutover going right. If your legacy system is holding your business back, that is a trade worth making. Talk to MTD Technologies about scoping your first slice.