A Strangler-Fig Migration Plan
Engineering

A Strangler-Fig Migration Plan

A gradual migration succeeds when each route has a clear owner, test, and way back. Build the route plan, data boundaries and cutover gates through a hypothetical order-history example.

Short answer

The Strangler Fig pattern moves legacy functionality to a new application incrementally behind a shared entry point. Give each route a data owner, behaviour contract, measurable cutover gate and tested rollback procedure. Retire old code only after confirming that traffic and background dependencies have stopped across the relevant business cycle.

What is the Strangler Fig pattern, and why use it for legacy migration?

The Strangler Fig pattern replaces an existing application's functionality gradually behind a shared entry point. Requests for migrated capabilities go to the new implementation; other requests continue to reach the old application. Users can keep the same address while individual parts change behind it. Microsoft's Strangler Fig guidance describes this routing approach and the retirement of the old system once its dependencies have been removed. The objective is to divide a large transition into smaller steps with evidence that each one works.

Installing a proxy does not complete the migration plan. You still need to determine which business rules the new component applies, which data it writes and whether the old application can resume service after a failure. The approach may be unsuitable when requests cannot be intercepted, necessary legacy changes cannot be made, or the old system must be fully retired quickly. For a small application that is straightforward to replace, operating two systems together can also add unnecessary cost.

Both applications remain live during the transition. Budget for their infrastructure, monitoring and support, and give every migration step a completion condition. Publishing new code is insufficient evidence of progress. An old route still called by a mobile client or an overnight job remains an active dependency. Route ownership and retirement evidence prevent the transitional architecture becoming an indefinite second product.

A route-by-route cutover plan

Start by drawing the connections between clients, incoming routes, authentication, background jobs and data writes. Select one capability with a measurable benefit and a manageable failure cost. A read-only catalogue may be an easier starting point than order creation because it has no payment or inventory side effects. The following table is an illustrative plan skeleton for an order portal, rather than a recommendation to migrate all five routes in one project.

Route or jobCutover gateRollback
Product catalogueFields and filters matchRestore the old read route
Order historyAuthorisation and pagination verifiedDisable cohort routing
Daily reportAmounts and freshness reconcileEnable the old report
Order creationSingle writer and safe retriesTransfer new records back
Overnight reconciliationBusiness cycle and dependencies verifiedRestore the old job carefully

Expand every row into a record containing route ID, business owner, technical owner, callers, data owner, rollout stage, acceptance criteria, rollback switch and the last legacy traffic timestamp. Link the test evidence and the decision authorising the next stage. The rollback cell for a write route is only a prompt: record conversion and ordering need their own tested procedure. If a shared transaction remains unresolved, the gate stays closed rather than treating the remaining work as a minor deployment detail.

How to establish routing and a behaviour contract

Initially send all traffic through the routing layer to the old system. Measure the layer's latency and failure behaviour before opening new functionality. Keep route and cohort assignments in versioned configuration, and prevent one user from switching randomly between implementations during the same workflow. Authentication, authorisation, request identifiers and support records should follow the same user operation across both paths. Define who can change the assignment and how that change is recorded.

Write the request and response contract: required fields, missing values, error codes, time zones, currencies, ordering and pagination. The business owner should approve which legacy behaviours must be preserved and which are intentional improvements. Order history needs more than matching record counts. A user must see only their own orders, and page boundaries must not duplicate or omit entries. Capture differences between historical data and the new model in concrete cases rather than relying on the shape of a successful response.

Microsoft's anti-corruption layer pattern places a translation boundary between systems with different semantics. An old delivery status might need mapping into separate dispatched and delivered states in the new model. Keep that mapping at a defined boundary rather than copying legacy conventions throughout new business code. Monitor translation latency and errors and decide when the adapter can be retired. A clean API name does not resolve a mistaken interpretation of the old data.

Data ownership, shadow traffic and progressive rollout

Name one authoritative writer at each stage. The new application might temporarily read the old database, use an existing API, or operate from a synchronised read model. Whichever option you choose, document its data source, freshness limit and behaviour when connectivity fails. Indefinite direct dependence on old tables preserves schema coupling even after application code has moved. Give transitional access a concrete exit condition, with an owner responsible for demonstrating that it is no longer needed.

Shadow traffic is appropriate only for reads or calculations that can be repeated without side effects. Executing the same order-creation request in both applications can create two orders or payments. Test write flows first in an environment where external side effects are disabled, using representative records. For production cutover, decide how new writes reconcile with the old application, how duplicates are identified and in what order cancellations are applied. Equal record counts do not prove that amounts and states agree. Preserve identifiers that let you investigate an individual transaction across the transition.

Microsoft's safe deployment guidance supports progressive exposure and health checks before each stage. Choose cohort sizes from traffic and business risk. Allow enough observation time for normal activity, peak usage and the relevant background job to run. A group receiving no requests supplies no evidence of success. Name the people who can expand the rollout, stop it and start recovery; the decision should be available when an alarm fires, not invented during an incident.

Hypothetical example: migrating order history

Suppose a portal receives 30,000 order-history queries per day. Its old route has p95 latency of 900 milliseconds and an error rate of 0.4%. The new route uses a read model supplied by the legacy API, with an agreed freshness delay of no more than 60 seconds. These numbers are hypothetical project targets, not customer measurements or thresholds suitable for every application. The support team owns the business result and the portal team owns technical operation. The first migration record names both responsibilities.

The team compares 2,000 representative read requests in shadow mode, checking identity, permissions, totals, ordering and pagination. It then moves 100 internal users to the new route and observes a full working day and the overnight synchronisation job. If there are no unexplained record differences, it opens the route to 5% of external users. In this example, p95 latency must remain at or below 900 milliseconds and errors at or below 0.4%. If freshness delay exceeds 60 seconds, expansion stops and configuration returns reads to the old path. Comparison evidence remains attached to the route record.

Even after all user traffic moves, the old route is not deleted immediately. If a month-end report still calls it, the dependency inventory and migration plan change. Completion requires no remaining calls across the relevant business cycle, reconciled data and a successful recovery drill. Record the last old-system call and investigate any subsequent hit before marking the route complete. That final observation may reveal a rarely used client that an ordinary working-day trial could not exercise.

A test plan for cutover gates

  1. Contract: Run representative inputs against both paths. Keep intentional changes separate from defects and attach approval for changed behaviour, including old clients and historical records.
  2. Authorisation: Call the same route under different identities and roles. New routing must preserve the previous access boundary even if authentication is handled by a shared gateway.
  3. Failure: Stop the new service and translation layer. Verify the switch, old-path capacity and the outcome of operations already in progress when recovery begins.
  4. Data: Exercise delayed updates, duplicates, cancellations and interrupted synchronisation. Reconcile amounts, states and identifiers, and assign ownership for any unexplained discrepancy.
  5. Rollout: Monitor errors, p95 latency, business outcomes and request counts by route and cohort. Open the gate only with enough real usage to support the decision.
  6. Retirement: Check mobile clients, file transfers and scheduled jobs for old dependencies. Verify a backup and reconstruction procedure before removing objects that recovery may still require.

Common mistakes

  • Treating the proxy as the migration plan while leaving business and data ownership unclear.
  • Moving several tightly coupled routes together and needlessly increasing the scope of rollback.
  • Running live write requests in shadow mode in both systems and duplicating external effects.
  • Applying one rollout percentage to every traffic level and declaring an unused cohort successful.
  • Deleting old code from front-end traffic evidence while missing overnight jobs and mobile clients.

How Hatson Tech builds this

In our custom software development work, we scope a migration through route inventory, data ownership and acceptance gates. Evaluate the proposed boundary with the exercise in when to split a monolith, and choose which application components to retain using the application modernisation decision guide. The initial deliverable brings the route plan, named owners, test evidence and recovery steps together. Sharing one candidate workflow and its current dependencies gives the first trial a concrete scope and makes its completion conditions reviewable before the next route moves.

Key takeaways

  • Select one capability with clear API and data boundaries and create its route record.
  • Test the routing layer against the old system first and keep cohort assignments consistent.
  • Do not shadow live write requests across both applications.
  • Gate each stage using usage, errors and reconciliation by route and cohort.
  • Prove that mobile clients and background jobs no longer depend on old code before retirement.

Frequently asked questions

What is the Strangler Fig pattern?

It replaces legacy functionality incrementally behind a shared entry point instead of replacing the whole system at once. Unmigrated functions remain on the old application, whose retirement depends on removing remaining dependencies.

How do you migrate a legacy system gradually?

Inventory callers and writes, then define the contract and acceptance gate for one route. Exercise representative cases, open a small cohort and approve the next stage from actual usage evidence.

Is Strangler Fig the same as microservices?

No: one is a migration approach and the other is an application architecture. Gradual migration can move a capability into a microservice or into another application component.

Is a rollback switch enough?

It may be enough for read routing, provided capacity and permissions have been tested. A route that writes new data also needs a proven way for the old application to handle and reconcile those records.

When can I shut down the old system?

Consider retirement when no callers or background dependencies remain across the relevant business cycle, data checks pass and recovery has been practised. A monthly job cannot be ruled out from daily traffic evidence alone.

All articles