The strangler fig pattern: modernizing without a big-bang rewrite

Women shopping online

A strangler fig migration doesn't fail on day one. It fails near the end, when the remaining slices turn out to be unscoped and the business has already banked the win.

The canonical write-ups from Fowler, Microsoft, and AWS explain the shape of the pattern well; they say far less about who owns data during the overlap, what the facade actually costs to run, or why teams stop halfway.

This guide picks up where those references stop. It assumes you have already decided to modernize rather than rebuild, and that rebuilding the application outright has been considered and set aside.

Strangler fig pattern, in two sentences

The strangler fig pattern replaces a legacy system one capability at a time, routing traffic through a facade until nothing points at the old code and the legacy system can finally be switched off. Martin Fowler named and defined the pattern in 2004, and that definition has not needed revising since.

What the canonical write-ups don't cover is the delivery reality: running two systems in parallel, paying for both, and keeping data consistent across them for the length of the migration. Across replatforming engagements we've watched facades scoped as temporary outlive the legacy systems they were meant to retire.

This guide picks up where Fowler's bliki defines the pattern, Microsoft Learn's Azure Architecture Center documents the reference implementation, AWS Prescriptive Guidance walks through delivery mechanics, and Wikipedia summarizes the consensus definition: routing cost, dual writes against change data capture, and the point where most migrations actually stall.

How the facade routes requests during migration

The facade layer is the single interception point in a strangler fig migration: every request from the client hits it first, and it decides whether the legacy system or the new system serves that request. Nothing else in the architecture needs to know a migration is happening.

In practice, teams build this facade as a reverse proxy or an API gateway sitting in front of both systems, matching on URL path, header, or feature flag rather than touching client code.

Martin Fowler's original 2004 bliki entry on the strangler fig application describes this exact mechanism: intercept the call, route it, and gradually shift more of the traffic to the new system as capabilities migrate.

Microsoft's Azure Architecture Center reference implementation deploys the facade as an API Management instance or Application Gateway, routing by path so migrated endpoints resolve to the new system and everything unmigrated falls through to the legacy system. AWS Prescriptive Guidance's strangler fig pattern takes the same shape with Amazon API Gateway or an Application Load Balancer as the interception point.

None of this runs for free. The facade is another service to deploy, monitor, and patch, and it sits on every request for as long as both systems run side by side, which is the whole duration of the migration, not a rollout window.

One distinction matters here: this facade is not an anti-corruption layer. An anti-corruption layer wraps a system you intend to keep; a strangler facade is scoped to disappear once the legacy system behind it is retired.

Who owns the data during the overlap?

Whoever writes last during the overlap owns the truth, and deciding that upfront is what separates a strangler fig migration that finishes from one that quietly corrupts its own data. This is the problem the reference architectures gloss over.

Two mechanisms handle synchronization. Dual writes push every update to both the legacy system and the new system from the application layer, which is simple to build and wrong under load: a partial failure between the two writes leaves one system ahead of the other with no record of which one is correct.

Change data capture reads the legacy database's write-ahead log and replays changes into the new system asynchronously, decoupling the write path entirely. According to Confluent's change data capture documentation, log-based CDC pipelines typically introduce replication lag of under a second when properly tuned, far lower than the minutes-long lag common in polling-based approaches.

Our experience across replatforming engagements is that teams default to dual writes because it fits inside a single sprint, then spend months afterward debugging drift that CDC would have made structurally impossible. Pick one system as the source of truth for each domain before the first slice ships, not after. Even with CDC in place, reconciliation is not optional.

Build the reconciliation job as a first-class output, not a cleanup task, and run it before cutover, not after the business has already assumed the migration is done.

The facade layer we described earlier does not solve this. It routes requests; it has no opinion on which database is right when the two disagree.

Which capability should you strangle first?

The right capability to strangle first is the one with the fewest upstream dependencies and the cleanest seam, not the one causing the most pain. This is where sequencing inside a strangler fig pattern migration usually goes wrong.

Teams pick the biggest, ugliest module first because it is the easiest win to sell internally. That module is almost always wired into shared mutable state: tables five other services write to, batch jobs nobody fully owns, fields nobody can rename without breaking a downstream report.

Strangling it first means building change data capture and reconciliation logic for the hardest data problem in the estate before the team has run the pattern once.

If you're weighing the strangler fig against other options, this other architecture patterns catalog breaks down when each approach fits best. We sequence the other way. Start with a capability that is read-heavy, has a narrow write surface, and sits behind an interface the facade layer can intercept without touching shared state.

Chris Richardson's pattern catalog frames the strangler application the same way: it fits loosely coupled capabilities with defined boundaries, not the most entangled ones. Prove the routing, the dual-write path, and the reconciliation job on low-risk ground first.

Save the module touching shared mutable state for last, once the team has a working ownership and rollback pattern, or exclude it entirely if the coupling can't be cut.

The same logic shapes monolith decomposition sequencing in practice.

Why strangler migrations stall at 80%

Strangler migrations rarely die at kickoff. They die at 80% done, when the remaining slices are the ones nobody scoped, the flagship capability is live, and the business has already banked the win.

The pattern of collapse is consistent. Early slices strangle cleanly because they were picked for clean seams. What is left are the domains everyone avoided during sequencing: batch jobs with undocumented side effects, a legacy system module three teams still write to directly, reporting pipelines that read the old schema because nobody owns migrating them.

None of this was ever a line item, so there is no budget request and no owner to raise one.

We have watched the facade absorb the blame here. It was scoped as a temporary routing layer, but with the legacy system still serving 15% of unmigrated traffic, retiring it stops being anyone's job.

The fix is structural, not motivational: fund the migration in decision gates tied to legacy system retirement, not to feature parity on the new system. Each gate should force an explicit answer to "what still writes to the old source, and who owns shifting it," before the budget for the next slice releases.

Martin Fowler's original strangler fig writing frames the facade as a means to an end. Treat the last 20% as a funded phase with its own gate, not a cleanup task, and it stops being the phase that never ships.

The real cost of running two systems in parallel

Running two systems in parallel costs more than a temporary bump during cutover: you run, patch, and monitor both stacks for the full length of the project. That means doubled infrastructure spend, doubled on-call coverage, and a monitoring surface nobody sized into the original business case.

The facade layer absorbs most of that hidden load. It gets scoped as a routing shim that disappears once the last slice cuts over. In practice, we've seen facades harden into permanent infrastructure, because the facade is the one component that intercepts every request touching both the legacy system and the new system.

It accrues its own logging, its own alerting rules, its own on-call runbook. A component nobody planned to maintain still needs a maintainer, and that maintenance cost rarely gets removed from the budget once the migration is declared done.

The data side compounds it. Every dual-write path, every change data capture pipeline, every reconciliation job is a second workload the team now owns, and someone has to decide which system holds the source of truth while both are live. That decision does not get easier the longer the migration runs, only more expensive to reverse.

Shared mutable state is where the cost stops being linear. When two systems write to the same database without a clear ownership boundary, race conditions surface only under production load, and reconciliation stops being a scheduled batch job and turns into a standing incident category. 94% of successful migrations kept legacy and new systems parallel for 3-6 months.

That erosion of engineering time is a big part of why technical debt tracking has to include the migration's own overhead, not just the legacy code it's replacing.

When not to use the strangler fig pattern

The strangler fig pattern fails when there is no interception point, when shared mutable state ties old and new code to the same data, or when the legacy system is small enough that a big-bang rewrite is genuinely cheaper.

Martin Fowler coined the term in 2004 to describe capability-by-capability replacement, and his own definition assumes you can insert a facade in front of the calls you are strangling. No interception point, no pattern. Batch jobs that read a database directly, tightly coupled desktop clients, and systems with no API layer or message bus in between all fall into this trap.

Shared mutable state is the harder blocker. If two services write to the same tables with no clear ownership boundary, a facade cannot decide which side owns a given row, and every dual write becomes a race condition instead of a migration step. Splitting that database is usually the real project, not the strangler work sitting on top of it.

Small estates change the math entirely. Below a certain size, the overhead of running two systems side by side for the length of a migration costs more than a focused rewrite, and the incremental approach only adds risk on top of that cost.

We have seen teams sink real engineering time into a facade for an application a small team could have rewritten outright, because nobody stress-tested the big-bang rewrite alternative before committing to the pattern.

Strangler fig vs. Big-bang rewrite: Which is cheaper?

A big-bang rewrite costs less upfront and more the moment it fails; the strangler fig pattern costs more upfront and less the moment the rewrite would have. That is the whole comparison, and it is a timing question, not a total-cost one.

A big-bang rewrite has one funding line and one cutover date. Budget it once, ship it once, sign off the business case once. The strangler fig pattern has no single cutover.

It runs the legacy system and the new system side by side, sometimes for years, and every month of overlap means paying for both: infrastructure, licenses, and the reconciliation work that keeps dual writes and change data capture from drifting apart.

Someone has to own that reconciliation job, and it rarely gets resourced past the first quarter.

The risk profiles diverge further than the budgets do. Large rewrite projects overrun their original budget and timeline more often than not. On average, large IT projects run 45% over budget and 7% over time (McKinsey Digital, 2012). A big-bang rewrite that fails does so late and all at once, with the legacy system already partly decommissioned.

A strangler migration that stalls usually stalls at 80% done, not zero, because the early slices already banked value the business has booked and stopped funding the rest.

We walk through the funding and decision-gate structure that prevents that stall in our modernization decision guide.

For an estate small enough to spec completely, a big-bang rewrite is often the honest cheaper answer. For anything you cannot fully scope upfront, the strangler fig pattern trades a lower guaranteed cost for a lower chance of losing the whole bet.

How do you Know the migration is finished?

The migration is finished when the legacy system carries zero production traffic and every domain it owned has a verified new-system owner, not when the last feature ships. Traffic share is the only metric that matters, because a facade layer can quietly keep routing a slice of reads to the old system long after the team believes the cutover is complete.

Check three things before calling it done: the facade layer routes 100% of both reads and writes to the new system, the reconciliation job has run clean (zero drift) for a full business cycle, not a single quiet day, and every downstream consumer of the legacy system's data or APIs has been repointed or formally deprecated.

Skip any one of these and you retire infrastructure someone else is still quietly depending on.

Decommissioning the facade layer is a separate decision from decommissioning the legacy system, and conflating them is how temporary infrastructure becomes permanent.

Once the legacy system is off, the facade has done its job: either remove it, or consciously convert it into a permanent integration layer with a new name, owner, and SLA, so it stops being tracked as "temporary" on a migration board nobody is looking at anymore.

We have seen facades scoped for a single quarter still routing traffic two years later, simply because no one owned the decision to remove them.

A rewrite has no equivalent moment, only a cutover date and whatever surfaces after it.

Strangler fig in monolith decomposition and microservices

Strangler fig applied to monolith decomposition means routing one bounded-context slice at a time behind a facade, not re-platforming the whole domain model in one pass. The pattern itself is scoped to migration; identifying where the service boundaries actually sit is a separate question, covered in our monolithic vs. microservices comparison.

Once boundaries are set, the facade intercepts reads and writes for the slice being migrated and leaves every other domain routed straight to the legacy system. Chris Richardson's decomposition patterns catalog on lists two primary strategies for drawing those lines, by business capability or by subdomain, and either works as strangler fig's unit of migration.

Feature flags are what make that per-slice cutover reversible. Flip traffic for one domain to the new system, watch it, and roll back to the legacy path without touching routing for domains still unmigrated. Without flags, each slice becomes a one-way door, which is how facades that were scoped as temporary end up staying in production long after the legacy system should have retired.

FAQ: Strangler fig pattern

When should you not use the strangler fig pattern?

Skip the strangler fig pattern when the legacy system has shared mutable state you cannot split, or no interception point exists between callers and the database. A monolith with a single shared table and no API layer often falls into this trap. In those cases, a scoped big-bang rewrite or a data-layer redesign first is the honest answer.

How long does a strangler fig migration take?

There is no fixed duration; it depends on how many capabilities need to be sliced out and how entangled the legacy system's data model is. Migrations that look finished at the final stretch frequently stalls because the remaining slices are the ones nobody scoped. Budget and staff for that last stretch, not just the visible early wins.

Strangler fig vs big-bang rewrite: Which is cheaper?

A big-bang rewrite is cheaper on paper because it avoids running two systems in parallel, but it carries higher delivery risk since nothing ships until the whole system is done. The strangler fig pattern costs more over its duration, since teams pay for legacy and new infrastructure simultaneously. Where risk of a failed cutover outweighs the extra parallel-running cost, the strangler fig pattern wins.

Deciding if strangler fig fits your migration

The strangler fig pattern earns its complexity when a legacy system is too large or risky to replace in one release. Validating that assumption costs nothing before committing engineering time to it.

If your team is weighing a new build against incremental replacement, unsure who owns data truth during the overlap, or wondering how reconciliation affects privacy obligations on regulated fields and terms privacy compliance, a short scoping conversation, available around the clock across time zones, clarifies sequencing and facade costs faster than a Google search will.

Talk to our team about your legacy system before it becomes the migration nobody scoped.

If you'd rather explore how a structured approach works in practice, our legacy commerce modernization services outline how teams sequence these migrations without derailing the business.

We're Netguru

At Netguru we specialize in designing, building, shipping and scaling beautiful, usable products with blazing-fast efficiency.

Let's talk business