The strangler fig pattern is an incremental approach to legacy application modernization.
Instead of replacing an entire application at once, teams introduce a stable interface, migrate one capability to a new implementation, redirect its callers, and retire the old functionality when it is no longer needed.
Unlike a full rewrite, this approach allows teams to deliver improvements gradually while controlling the risk of each change.
| Stage | What happens | What to verify |
|---|---|---|
| Before | Legacy app handles requests | Map callers and dependencies |
| During | New and old services run together | Route traffic and compare behavior |
| After | Migrated capability runs separately | Retire old paths only when safe |
How does the strangler fig pattern work?
The pattern typically has three stages.
Before migration
All requests are handled by the existing legacy application.
The application may contain tightly coupled business logic, integrations, and data access.
During migration
A routing or API layer sits in front of the application.
Some requests continue to the legacy implementation, while selected capabilities are handled by new services.
Both systems operate during the transition, but their responsibilities should be explicit.
After a capability has moved
The migrated capability runs in the new service.
Other capabilities continue using the legacy application until they’re ready to move.
Once the old implementation has no remaining callers or dependencies, it can be retired.
When should you use the strangler fig pattern?
The pattern is useful when:
- The existing application is too important to replace in one release.
- Some capabilities need frequent changes while others remain stable.
- The application contains undocumented dependencies.
- A full rewrite would require extensive migration and testing.
- Teams need to demonstrate business value before completing the broader modernization program.
It works best when capabilities can be separated behind stable interfaces.
The approach is more difficult when functionality shares extensive mutable state or when business rules and data writes cannot be isolated.
How to implement the strangler fig pattern step by step
- Map the existing system. Identify application entry points, APIs, screens, scheduled jobs, file feeds, and integrations. Document which capabilities depend on each other and where their data lives.
- Introduce a routing boundary. Place a stable API or routing layer in front of the legacy application. Initially, the new layer can forward requests to the existing implementation without changing behavior. This gives callers a consistent interface while allowing the implementation behind it to evolve.
- Choose the first capability. Start with a well-bounded function that has clear inputs and outputs, limited shared data, and a meaningful business benefit. A small approval or validation workflow may be a better starting point than a tightly coupled core transaction engine.
- Capture existing behavior. Create tests for the legacy implementation, including normal inputs, exceptions, permissions, errors, and side effects. These tests provide a baseline for evaluating the replacement.
- Build and validate the replacement. Implement the capability behind the routing boundary. Compare its behavior with the legacy version using equivalent inputs. Avoid duplicate real-world side effects when running comparisons.
- Shift traffic gradually. Move a controlled group of requests to the new implementation. Monitor behavior, maintain a rollback option, and verify data ownership and consistency.
- Retire the legacy path. Confirm that all callers, scheduled jobs, integrations, and relevant data dependencies have moved. Then remove the old implementation. Track the remaining legacy dependencies to demonstrate progress.
Worked example: Replacing an approval workflow
Imagine an order management system that handles order entry, fulfillment, billing, and approvals.
Approval rules change frequently, but fulfillment is stable.
Replacing the entire application would introduce unnecessary risk.
Instead, the team can migrate approvals independently.
Stage 1: Establish the interface
Create an API endpoint for approval requests. Initially, it calls the existing stored procedure.
Stage 2: Capture behavior
Document the current rules, permissions, errors, and side effects.
Stage 3: Build the replacement
Implement approval logic in a new service and compare its decisions with the legacy procedure.
Stage 4: Redirect requests
Gradually route approval requests to the new service while monitoring differences.
Stage 5: Retire the old rule
Once all callers have moved and dependencies are addressed, remove the legacy approval path.
The rest of the order management system continues operating throughout the transition.
How do you avoid running two systems forever?
One of the biggest risks in incremental modernization is permanent dual maintenance.
A new service may be deployed successfully while the old implementation remains active because nobody has completed the migration.
To avoid this, define retirement criteria before beginning.
| Area | Retirement requirement |
|---|---|
| Traffic | All relevant callers use the new implementation |
| Data | Write ownership and consistency are established |
| Integrations | External systems and scheduled jobs no longer depend on the old path |
| Testing | Replacement behavior has been validated |
| Monitoring | The new implementation can be supported and investigated |
| Operations | An owner is accountable for the new service |
| Legacy code | The old implementation can be safely removed |
Data ownership deserves particular attention.
If both systems can write to related records, define transaction boundaries, synchronization, and reconciliation before shifting traffic.
A routing layer alone doesn’t solve data consistency.
Incremental migration checklist
Use this checklist for each capability.
- Choose a capability with clear inputs and outputs.
- Document existing behavior and dependencies.
- Introduce a stable routing boundary.
- Define data ownership and transaction behavior.
- Build the replacement and compare results.
- Establish rollback and stop conditions.
- Shift traffic gradually.
- Verify that all callers and integrations have moved.
- Remove the old implementation and its dependencies.
A migration is complete when the old capability is no longer needed, not merely when the new one works.
How Xano helps implement the strangler fig pattern
Xano can serve as the API routing and business-logic layer between applications and an existing legacy system.
Teams can publish stable endpoints while deciding whether individual requests should be handled by legacy services or new workflows in Xano.
With Xano, teams can:
- Introduce a stable API boundary. Give applications a consistent interface while changing the implementation behind it.
- Connect to existing systems. Call legacy APIs or query existing databases.
- Centralize authentication. Apply authentication at the API layer where appropriate.
- Move logic incrementally. Replace individual workflows without rebuilding the entire application.
- Test replacement behavior. Use unit and workflow tests before switching traffic.
- Investigate failures. Use request history and error logs.
- Prepare controlled releases. Use branches, sandboxes, and releases to validate changes.
This supports incremental modernization while the legacy system continues handling capabilities that haven’t moved.
Common questions about the strangler fig pattern
Modernize a capability, then retire the old one
The value of the strangler fig pattern isn’t that old and new systems can run side by side.
It’s that teams can stop running old functionality one capability at a time without interrupting the business.
Choose a bounded capability, prove the replacement, move its callers and data ownership deliberately, and retire the old path.
That’s how incremental modernization remains a migration rather than becoming a permanent second system.


