What the Strangler Fig Pattern Actually Does
When to Use the Strangler Fig Pattern
Step 1: Map the System Before You Touch It
Step 2: Install the Routing Layer
Step 3: Extract the First Service
Step 4: Handle the Data Problem
Step 5: Expand the Migration Systematically
Step 6: Manage the Migration as a Product Concern
Step 7: Retire the Legacy System
Common Failure Modes
The Strangler Fig Pattern and AI-Assisted Modernisation
When to Bring in External Support
FAQs
The strangler fig pattern is one of the most practical approaches a team can take when modernising a legacy system without stopping the world to do it. Named after the tropical plant that grows around a host tree and gradually replaces it, the pattern lets you decompose a monolith incrementally — routing traffic to new services piece by piece while the old system keeps running. No big-bang rewrite. No six-month freeze on feature work. No betting the company on a single migration sprint.
If your team is staring down a codebase that has become difficult to change, slow to deploy, and expensive to maintain, this guide walks through how to implement the strangler fig pattern in practice — not just the theory, but the sequencing, the decision points, and the traps that derail teams mid-migration.
What the Strangler Fig Pattern Actually Does
The pattern works by introducing a proxy layer — often called a facade or routing layer — that sits in front of the legacy system. New functionality is built as separate services. Over time, the proxy routes more and more requests to those new services. The legacy system handles less and less traffic. Eventually, it is retired.
The key insight is that the legacy system and the new services coexist throughout the migration. Users see no disruption. The team ships continuously. Risk is distributed across many small decisions rather than concentrated in a single cutover.
This is fundamentally different from a rewrite. A rewrite asks you to rebuild everything before you can ship anything. The strangler fig pattern asks you to identify the first slice worth replacing, replace it, and move on to the next.
When to Use the Strangler Fig Pattern
Not every legacy modernisation problem calls for this approach. The strangler fig pattern is the right choice when:
The existing system is in production and cannot be taken offline
The codebase is large enough that a full rewrite would take more than three months
Different parts of the system have different change rates — some modules change constantly, others have been stable for years
The team needs to keep shipping features while the migration is underway
The architecture needs to evolve toward microservices or a more modular structure
It is less appropriate when the system is small enough to rewrite cleanly in a few weeks, when the data model is so tightly coupled that decomposition requires a full schema redesign, or when the team lacks the infrastructure maturity to run two systems in parallel.
If you are unsure whether your situation calls for the strangler fig pattern or a different approach, the 12-week legacy modernisation framework covers the diagnostic phase in detail — including how to assess coupling, change frequency, and migration risk before committing to a strategy.
Step 1: Map the System Before You Touch It
The first move is not to write code. It is to understand what you have.
You need a clear map of the legacy system's boundaries: which modules exist, what each one does, how they communicate, and which parts of the system are most actively changed. This is not a full architectural audit — it is a targeted exercise to identify where the strangler fig pattern will start.
Focus on three things during this mapping phase.
Inbound entry points. Where does traffic enter the system? HTTP routes, message queue consumers, scheduled jobs, and API endpoints are all entry points. You need to know every door into the building before you start rerouting traffic.
Data ownership. Which module owns which data? Shared database tables are the most common source of coupling in legacy systems, and they will slow down every decomposition step if you do not account for them early.
Change frequency. Which modules have been modified most in the last six months? High-change areas are usually the best candidates for early extraction — they are where the pain is most acute and where a cleaner architecture will deliver the fastest return.
AI-assisted legacy code analysis can surface dependency maps, identify tightly coupled modules, and flag areas of high churn far faster than manual review. For large codebases, this step can take days rather than weeks when done with the right tooling.
Step 2: Install the Routing Layer
Before you extract a single service, you need the infrastructure that makes coexistence possible. This is the routing layer — sometimes called the strangler facade.
The routing layer sits in front of both the legacy system and any new services you build. It receives every inbound request and decides where to send it. Initially, it forwards everything to the legacy system. As you extract services, you update the routing rules to direct specific requests to the new services instead.
The routing layer can be implemented in several ways depending on your stack:
An API gateway (AWS API Gateway, Kong, or a custom Nginx configuration) for HTTP-based systems
A message broker with topic routing for event-driven architectures
A reverse proxy with path-based routing rules for monolithic web applications
The critical requirement is that the routing layer must be independently deployable. If updating a routing rule requires a full application deployment, you lose the agility that makes the pattern work. Treat the routing layer as infrastructure, not application code.
At this stage, the legacy system is still handling 100% of traffic. No behaviour has changed. You have only introduced a seam.
Step 3: Extract the First Service
Now you choose what to extract first. The right first extraction is not necessarily the most important module — it is the one that teaches the team how the pattern works in your specific environment with the least risk.
Good candidates for a first extraction:
A module with a clear, narrow interface — few inbound calls, few outbound dependencies
A module that does not share database tables with the rest of the system
A module with high change frequency, where the team will immediately benefit from the cleaner architecture
A module that can be tested in isolation without requiring the full legacy system to be running
Build the new service. Deploy it. Write the tests. Then update the routing layer to send the relevant traffic to the new service. Monitor closely. If something goes wrong, you can route traffic back to the legacy system without touching the new service.
This first extraction is as much a proof of concept for your deployment pipeline and monitoring setup as it is a functional migration. The team needs to confirm that the pattern works end-to-end in your environment before scaling it up.
Step 4: Handle the Data Problem
Data is where most strangler fig migrations slow down or stall. The legacy system almost certainly has a shared database, and new services need their own data stores to be truly independent.
There are three approaches, and the right one depends on how tightly coupled the data is.
Separate the schema first. If the module you are extracting owns its data cleanly — meaning no other module writes to those tables — you can copy the schema into a new database, migrate the data, and update the new service to read and write to the new store. The legacy system continues using the old tables until it is retired.
Dual-write during transition. If the data is shared, you may need a period where both the legacy system and the new service write to both databases, with a reconciliation process to keep them in sync. This is operationally complex but sometimes unavoidable.
Event-driven synchronisation. For systems that can tolerate eventual consistency, publishing change events from the legacy system and consuming them in the new service is a cleaner long-term approach. It requires more infrastructure investment upfront but pays off when you are running multiple new services in parallel.
The worst outcome is leaving the new service dependent on the legacy database. It creates a hidden coupling that will constrain every architectural decision downstream. Resolve the data ownership question for each extraction before moving on.
Step 5: Expand the Migration Systematically
Once the first extraction is running cleanly in production, you have a repeatable process. The team now knows how to build a new service, update the routing layer, handle data migration for this specific system, and monitor a cutover.
The next extractions follow the same sequence: map the module, build the service, deploy it, migrate the data, update the routing, monitor, and move on. The pace depends on team capacity and the complexity of each module, but the pattern does not change.
At this stage, the decisions that matter most are about sequencing:
Which modules to extract next, based on change frequency and coupling
Whether to tackle a high-coupling module now or wait until surrounding modules have been extracted and the coupling has been reduced
When to retire legacy code rather than leaving it running indefinitely
That last point matters more than most teams expect. Once a module has been replaced and the routing layer updated, the legacy code for that module should be deleted within a defined window — 30 days is a reasonable default. Leaving dead code in place creates confusion and maintenance overhead. Set the policy early and hold to it.
Step 6: Manage the Migration as a Product Concern
The strangler fig pattern is not purely a technical exercise. It runs in parallel with feature development, and the team needs a way to manage the migration as a first-class concern rather than a background task that gets deprioritised every sprint.
The practical approach is to treat migration work as a separate workstream with its own capacity allocation. A common split is 70% feature work, 30% migration work — adjusted based on how urgent the modernisation is and how much the legacy system is slowing down feature delivery.
The migration also needs visibility at the leadership level. The people making decisions about engineering priorities need to understand what percentage of the system has been migrated, what the expected timeline to full retirement looks like, and what the risk profile is at each stage. This is where the fractional CTO guide for scale-ups is directly relevant — technical leadership that can translate migration progress into business terms is often the difference between a migration that completes and one that stalls at 60%.
Step 7: Retire the Legacy System
The final step is the one teams most often underestimate. Retiring the legacy system requires more than turning it off.
You need to verify that no traffic is still reaching the legacy system — routing logs will confirm this. You need to confirm that all data has been fully migrated and that the new services are the authoritative source of truth for every data domain. You need to decommission the infrastructure: not just stop the application, but remove the servers, databases, and associated costs.
The routing layer also needs attention. Once the legacy system is gone, the routing layer is simply a proxy for the new services. At that point, you may choose to simplify or remove it, depending on whether it still serves a purpose in your architecture.
Document what was retired and when. This is not bureaucracy — it is the record that tells the next engineer on the team why the architecture looks the way it does.
Common Failure Modes
Teams that struggle with the strangler fig pattern tend to encounter the same problems repeatedly.
The routing layer becomes a bottleneck. If it is not independently deployable, every routing change requires a full deployment cycle. This slows the migration and creates pressure to batch changes, which increases risk.
Data coupling is underestimated. The team extracts a service and then discovers that three other modules are writing to the same tables. The extraction is incomplete and the new service is not truly independent. The fix is to do the data mapping work before extraction, not during it.
The migration loses priority. Feature pressure is constant. Without explicit capacity allocation and leadership visibility, migration work gets squeezed out of sprints. The legacy system keeps accumulating technical debt while the team builds new features on top of it.
The team extracts the wrong things first. Starting with a high-coupling, high-complexity module is a common mistake. The first extraction should be chosen for learnability, not importance.
The legacy system is never fully retired. The migration reaches 80% and stalls. The remaining 20% is the hardest, most coupled part of the system, and the team has lost momentum. The solution is to plan for this from the start — the last extractions should be scheduled and resourced as explicitly as the first ones.
The Strangler Fig Pattern and AI-Assisted Modernisation
AI tooling is changing the economics of legacy analysis in a meaningful way. The mapping work in Step 1 — understanding module boundaries, data ownership, and change frequency — used to take weeks for large codebases. With AI-assisted analysis, that timeline compresses significantly.
The practical guide to AI agent integration for engineering teams covers how production AI agents can accelerate this kind of analysis work. The key distinction is between AI tooling that assists developers internally and AI agents deployed as part of the production architecture — both have a role in modernisation, but they serve different purposes.
For teams running a strangler fig migration, AI-assisted analysis is most valuable in the early phases: dependency mapping, identifying dead code, surfacing hidden coupling, and generating a prioritised extraction sequence. It does not replace the architectural judgment required to make the right sequencing decisions, but it significantly reduces the time needed to gather the information those decisions depend on.
When to Bring in External Support
The theory behind the strangler fig pattern is sound. The implementation is where teams run into trouble — particularly when the legacy system is large, the data model is complex, or the team is simultaneously under pressure to ship features.
External support is most valuable at two points: the initial mapping and sequencing phase, where the decisions made will shape the entire migration, and the point where the migration has stalled and needs to be restarted with a clear plan.
We work with scale-ups on exactly this kind of engagement — embedded engineering pods running the migration workstream in parallel with the product team's feature work, with Fractional CTO oversight to ensure the architectural decisions are sound. If you are at an inflection point with a legacy system and need a clear path forward, the starting point is a conversation at wireapps.co.uk.
FAQs
What is the strangler fig pattern in software development?
The strangler fig pattern is an incremental modernisation approach where new services are built alongside a legacy system, traffic is gradually routed to the new services, and the legacy system is retired piece by piece. It avoids the risk of a full rewrite by allowing the old and new systems to coexist throughout the migration.
How long does a strangler fig migration typically take?
The timeline depends on the size and complexity of the legacy system. A focused extraction of a single module can take two to four weeks. A full migration of a large monolith typically runs six to eighteen months, depending on team capacity and the number of modules being extracted.
What is the difference between the strangler fig pattern and a rewrite?
A rewrite rebuilds the entire system before shipping anything new. The strangler fig pattern extracts and replaces one module at a time while the legacy system continues running. Rewrites carry concentrated risk. The strangler fig pattern distributes that risk across many smaller decisions.
What infrastructure do you need to implement the strangler fig pattern?
At minimum, you need a routing layer (API gateway, reverse proxy, or message broker), independent deployment pipelines for the new services, and monitoring that covers both the legacy system and the new services simultaneously. The routing layer must be independently deployable — this is a hard requirement.
How do you handle shared databases during a strangler fig migration?
Shared databases are the most common source of friction. The options are schema separation (where the module owns its data cleanly), dual-write synchronisation during transition, or event-driven synchronisation for eventual consistency. The goal is for each new service to own its data independently before the legacy system is retired.
When should you not use the strangler fig pattern?
The pattern is less appropriate for small systems that can be rewritten cleanly in a few weeks, for systems where the data model is so tightly coupled that decomposition is practically impossible, or for teams that lack the infrastructure maturity to run two systems in parallel safely.
How do you prevent a strangler fig migration from stalling?
Treat migration work as a first-class workstream with explicit capacity allocation — not a background task. Set a policy for retiring legacy code once it has been replaced. Ensure leadership has visibility into migration progress. Choose early extractions for learnability rather than importance, so the team builds confidence and momentum before tackling the most complex modules.
The strangler fig pattern works. The teams that succeed with it are the ones who take the mapping phase seriously, invest in the routing layer before extracting anything, resolve data ownership explicitly at each step, and maintain migration momentum alongside feature delivery. The pattern is not complicated — but it requires discipline, clear sequencing, and the architectural judgment to make the right call at each decision point.
Share




