Back to catalog
Architecture & Modernization

How Does the Strangler Fig Pattern Modernize Legacy Applications?

Updated 6 min read Article

> quick_answer

The key is to replace functionality without forcing the business to stop using the application during the migration.

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.

MODERNIZE WITHOUT A REWRITEStrangler fig: the interface stays while capabilities move01Before02During03AfterClientweb · partnersLegacy applicationone deployableapprovalsordersfulfillmentShared databaseevery module writes hereClientunchangedStable routing / API boundary/approvals/ordersNew serviceapprovalsliveLegacy apporders · fulfillmentold approvalsno longer calledApprovals datawrites: new serviceLegacy databasewrites: legacy appClientunchangedStable API/approvals/ordersNew serviceapprovalsmigratedLegacy apporders · fulfillmentold approvalsretiredApprovals datawrites: new serviceLegacy databasewrites: legacy app

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

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.

AreaRetirement requirement
TrafficAll relevant callers use the new implementation
DataWrite ownership and consistency are established
IntegrationsExternal systems and scheduled jobs no longer depend on the old path
TestingReplacement behavior has been validated
MonitoringThe new implementation can be supported and investigated
OperationsAn owner is accountable for the new service
Legacy codeThe 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.

Implement this in Xano - Test Suites

Common questions about the strangler fig pattern

Define retirement criteria, assign an owner to removing old functionality, and track remaining callers, writes, and dependencies.
Sometimes, but write ownership, transaction boundaries, and schema compatibility must be explicit.
A frequently changed, well-bounded capability with limited shared state and behavior that can be verified through tests.
It depends on the application, dependencies, and scope. Individual capabilities may be migrated in short iterations, while larger modernization programs can take years. The important measure is whether each iteration delivers value and reduces legacy dependencies.

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.