The Strangler pattern migration lets you replace a legacy monolith with microservices incrementally, keeping production live throughout, so your team delivers business value on every sprint instead of betting everything on a single cutover day.
TL;DR: If you have a large, brittle monolith you can intercept at the network layer, the Strangler Fig pattern coined by Martin Fowler is the lowest-risk path to microservices. Expect an enterprise-scale effort measured in months, not weeks.
Key components and constraints to plan for:
- Routing facade: A reverse proxy or API gateway that intercepts every request and directs traffic to either the legacy system or a new service.
- Anti-Corruption Layer (ACL): Translation adapters that prevent legacy data models from leaking into new services.
- Data synchronization strategy: Change Data Capture (CDC), dual-write, or a full database split, each with distinct trade-offs.
- Timeline: Enterprise migrations commonly run over an extended period; data disentanglement and comparator pipelines are the longest activities.
- When not to use it: If you cannot intercept traffic at the network layer, or if the system is small enough to replace in a single sprint, a full rewrite or lift-and-shift is simpler.
Table of Contents
- Why teams choose the Strangler approach over a big-bang rewrite
- How the Strangler pattern works end-to-end
- Signals that the Strangler pattern fits your system — and when it doesn’t
- Step-by-step migration plan from discovery through decommission
- How to handle data: split DB, CDC, outbox, and consistency trade-offs
- Technical building blocks: facade, ACL, observability, and CI/CD
- Frequent mistakes that turn a Strangler migration into a liability
- Walkthrough: migrating an Order/Checkout capability
- How the Strangler approach compares to the alternatives
- How Golden Path Digital runs Strangler migrations
- Key Takeaways
- The part most migration plans get wrong
- Golden Path Digital can map your migration before you move a line of code
- Useful sources and further reading
- FAQ
Why teams choose the Strangler approach over a big-bang rewrite
Legacy monoliths accumulate risk in ways that only become visible when you try to change them. Undocumented edge cases hide in decade-old code paths. Deployment pipelines are fragile because every component ships as one unit. A single bad release can take down the entire system, and the blast radius of any change is effectively the whole application.
The business cost of that fragility compounds over time. Teams slow down. Feature delivery stretches from days to months. And the temptation to schedule a “big-bang rewrite” grows, even though the historical failure rate of full rewrites is well-documented across the industry.
Big-bang rewrite vs. incremental strangler approach: A full rewrite freezes feature development for months or years, requires the new system to be feature-complete before any user sees it, and carries the risk of discovering critical edge cases only after cutover. The Strangler approach keeps the legacy system in production, extracts one capability at a time, and lets your team validate each slice in real traffic before committing to it.
The Microsoft Azure Architecture Center frames this precisely: the facade routes requests between legacy and new systems, so neither the business nor end users experience a flag day. Each extraction is a contained, reversible step. That reversibility is what makes the pattern attractive to risk-conscious architects — you can roll back a single slice without touching anything else.

How the Strangler pattern works end-to-end
The pattern moves through five distinct states, each with clear entry and exit criteria.

| State | What happens | Control point |
|---|---|---|
| 1. Facade introduced | A reverse proxy or API gateway sits in front of the monolith; all traffic passes through it unchanged | Verify zero behavioral change in production |
| 2. Incremental extraction | New services are built for targeted capabilities; facade routes a subset of traffic to them | Feature flags or path-based routing rules |
| 3. Parallel run | New service and legacy system handle the same requests; responses are compared via shadow traffic | Comparator tooling; diffing alerts |
| 4. Final cutover | All traffic for the extracted capability routes to the new service; legacy code path is disabled | Canary percentage ramp; rollback switch |
| 5. Decommission | Legacy code, tables, and dependencies for that capability are deleted | Deletion PR merged; schema cleaned |
The facade is the architectural linchpin. It can route by URL path, HTTP header, user segment, or runtime feature flag. Path-based routing is the simplest to configure and the easiest to audit; feature-flag-driven routing adds runtime flexibility but requires a flag management system. The key discipline is that every routing rule must be reversible in under five minutes. If rolling back a cutover requires a deployment, your rollback strategy is too slow.
Reversibility applies at every state transition, not just the final cutover. Introducing the facade must be a zero-change operation from the user’s perspective. Parallel runs must not alter the response the user receives. Each step is a checkpoint, not a commitment.
Signals that the Strangler pattern fits your system — and when it doesn’t
Use the Strangler approach when:
- The monolith is large, complex, and has been in production long enough to accumulate undocumented behavior.
- You can intercept all client requests at the network layer (HTTP, message broker, or event bus).
- You have access to the legacy source code and can instrument it for observability.
- The migration horizon is measured in quarters, not weeks, and the business can sustain incremental delivery.
- Clear business capabilities exist that map to bounded contexts (orders, inventory, billing, authentication).
Avoid it when:
- You cannot place a facade in front of the system (tightly coupled desktop clients, binary protocols with no proxy option).
- The legacy system has no source code access and no instrumentation hooks.
- The system is small enough that a clean rewrite takes less time than building and maintaining a facade.
- Regulatory constraints require a hard cutover with a certified, tested snapshot of the new system.
Pro Tip: Pick your first slice by change frequency, not by size. The capability your team touches most often in the current monolith is the highest-leverage starting point — once it lives in a new service, all future feature work flows there instead of back into the legacy codebase.
Practitioner guidance consistently reinforces this: starting with the most-changed, highest-leverage capability builds momentum and keeps the new system ahead of the legacy one in terms of active development.
Step-by-step migration plan from discovery through decommission
Phase 1: Discovery and dependency mapping
Before writing a single line of new service code, inventory the monolith. Map every HTTP endpoint, message consumer, and batch job. Document data ownership: which tables does each capability read and write? Measure change frequency per module over the last 12 months using your version control history.
This inventory is not optional. Teams that skip it discover mid-migration that a “simple” capability shares a table with six others, turning a two-week slice into a three-month data project.
Phase 2: Slicing strategy
Slice by vertical business capability first. A vertical slice owns its own data, its own API surface, and its own deployment pipeline. Avoid horizontal slices (e.g., “extract the authentication library”) because they create shared dependencies that block future extractions.
Sequence slices so that each one reduces the blast radius of the next. Extract the capability with the fewest inbound dependencies first. Once it is live, the monolith’s surface area shrinks, and subsequent slices become cleaner.
Phase 3: Engineering steps for each slice
- Build the new service with its own repository, CI/CD pipeline, and infrastructure-as-code definition.
- Write automated tests covering the behavioral contract of the capability, not just unit coverage. Include integration tests against the facade.
- Instrument for observability before the service handles any production traffic. Latency, error rate, and throughput baselines must exist before cutover.
- Implement dual-write or CDC so the new service’s data store stays synchronized with the legacy database during the parallel run.
- Run shadow traffic: route a copy of live requests to the new service without returning its response to users. Compare responses against the legacy system using a comparator.
- Migrate reads: once the comparator shows consistent responses, switch read traffic to the new service while writes still go to legacy.
- Migrate writes: cut over write traffic. Keep the legacy path available for rollback for at least one full business cycle.
- Decommission: delete the legacy code path, drop the now-unused tables, and remove the routing rule.
Pro Tip: Keep the facade as permanent production infrastructure, not a temporary scaffold. It becomes your traffic control plane for canary deployments, A/B tests, and future extractions. Teams that treat it as disposable rebuild it from scratch on the next migration.
Pro Tip: Always run a parallel comparator before cutting over writes. Shadow traffic and response diffing catch behavioral differences that test suites miss — especially around timezone handling, rounding, and legacy null-coalescing logic.
Phase 4: Operational tasks
Configure percentage-based canary routing at the facade level. Start at 1%, watch error rates and latency for 30 minutes, then ramp to 10%, 25%, 50%, and 100% with defined hold periods at each step. Document a rollback runbook before the canary starts, not after something goes wrong.
How to handle data: split DB, CDC, outbox, and consistency trade-offs
Data is where most Strangler migrations stall. Shared schemas, cross-table joins, and the need for consistency across two systems running in parallel are harder engineering problems than the service code itself.

The four canonical approaches, compared across the dimensions that matter most:
| Strategy | Risk reduction | Time to value | Complexity | Data migration difficulty | Team skills required |
|---|---|---|---|---|---|
| Legacy read API | Low (no data movement) | Fast | Low | Minimal | REST/HTTP, contract testing |
| CDC-based replica | Medium | Medium | Medium | Moderate (stream lag, ordering) | Kafka/Debezium, event streaming |
| Transactional outbox + dual-write | High | Medium | High | High (idempotency, compensation) | Distributed systems, saga patterns |
| Full DB split | Highest (long-term) | Slow | Very high | Very high (schema redesign, migration scripts) | DBA expertise, data engineering |
The legacy read API approach calls the monolith’s existing endpoints to fetch data the new service needs. It is the fastest path to a working service but creates a runtime dependency on the legacy system that must eventually be broken.
CDC-based replication uses tools like Debezium to stream database change events into the new service’s data store. Stream lag and event ordering require careful handling, but the approach avoids modifying the legacy application.
The transactional outbox pattern is the safest dual-write technique. The new service writes to its own database and an outbox table in the same transaction; a relay process publishes outbox events to a message broker. This eliminates the dual-write consistency gap without distributed transactions. Sagas and compensation logic handle failures across service boundaries.
Full DB split is the most ambitious option and the one that delivers the cleanest long-term architecture. It requires schema redesign, data migration scripts, and reconciliation pipelines. Reserve it for capabilities where the data model is genuinely incompatible with the legacy schema.
Pro Tip: Never allow two services to share a database schema, even temporarily. Shared schemas create invisible coupling: a schema change in one service breaks another, and you lose the deployment independence that microservices are supposed to provide. The legacy database migration discipline applies here — own your schema or own your risk.
Cross-table join replacement deserves a specific warning. When a capability’s queries span multiple tables owned by different future services, each join becomes a service-to-service API call or an event-driven aggregation. The cost of that replacement is routinely underestimated during planning.
Technical building blocks: facade, ACL, observability, and CI/CD
Routing facade options
Your facade choice shapes the entire migration. Three common options:
- Reverse proxy (NGINX, HAProxy, Envoy): Static configuration, low latency overhead, easy to audit. Best for path-based and header-based routing where rules change infrequently. Practitioner write-ups include working NGINX routing snippets that teams can adapt directly.
- API gateway (AWS API Gateway, Kong, Azure API Management): Adds authentication, rate limiting, and observability out of the box. Higher operational overhead but appropriate when the facade needs to enforce cross-cutting policies.
- Backend for Frontend (BFF): A thin application layer that aggregates calls for a specific client type. Useful when different clients (mobile, web, third-party) need different response shapes from the same underlying services.
Feature-flag-driven routing (LaunchDarkly, Unleash, or a custom flag store) adds runtime flexibility: you can shift traffic percentages without a deployment. The trade-off is an additional dependency in the critical path of every request.
Anti-Corruption Layer patterns
The ACL sits between the new service and any legacy system it must call. Its job is to translate legacy data models, field names, and error codes into the new service’s domain language. Without it, legacy concepts leak into new code and you end up rebuilding the monolith’s data model in a distributed form.
Implement ACLs as explicit adapter classes with contract tests. The contract test verifies that the adapter correctly translates a known legacy response into the expected domain object. When the legacy system changes, the contract test fails before the new service breaks in production.
Observability and verification checklist
- Distributed tracing (OpenTelemetry) across facade, new service, and legacy system from day one.
- Request/response comparator running against shadow traffic before any cutover.
- Latency and error rate dashboards with alerting thresholds set before the canary starts.
- Data reconciliation jobs that compare record counts and checksums between legacy and new data stores during dual-write phases.
- Runbook for each routing rule: what triggers a rollback, who owns the decision, and how long the rollback window stays open.
Deployment and rollback controls
Canary deployments at the facade level give you a rollback that takes seconds: flip the routing percentage back to zero. Pair that with a feature flag that disables the new service entirely if a critical bug surfaces. Own the facade configuration in version control so every routing change has a code review and a clear author.
Frequent mistakes that turn a Strangler migration into a liability
The most common failure mode is not a technical one. It is organizational: teams extract services but never decommission the legacy code paths they replaced.
The “final 5%” problem: Once a capability is running in the new service and the business is satisfied, the pressure to formally delete legacy code drops to near zero. The old code path stays “just in case,” the shared database tables remain, and within 18 months the team has a distributed monolith — all the operational complexity of microservices with none of the independence. Governance must treat decommissioning as a hard deliverable, not an optional cleanup task. Set a deadline at the start of each slice, not after cutover.
Other pitfalls to watch for:
- Shared database reliance: Two services reading and writing the same tables. The signal is a JOIN in a new service’s query that touches a table the legacy system owns. Mitigation: enforce schema ownership from the first slice.
- Poor slice boundaries: Slicing by technical layer (all controllers, all repositories) instead of by business capability. The result is services that cannot deploy independently. Mitigation: validate each slice against the “can this deploy without touching any other service?” test before building.
- Lack of observability: Cutting over traffic before baselines exist. You cannot detect a regression you have no metric for. Mitigation: instrument before routing, not after.
- Adapter hell: ACLs that grow into complex translation engines because the legacy data model was never cleaned up. Mitigation: treat each ACL as temporary; schedule its removal when the legacy dependency it wraps is decommissioned.
- Skipping parallel runs: Teams under schedule pressure skip shadow traffic and go straight to canary. Red Hat’s practitioner guidance warns explicitly that without a plan to validate behavior before cutover, organizations risk long-lived hybrid systems that are expensive to maintain.
Walkthrough: migrating an Order/Checkout capability
Order/Checkout is a strong first candidate for most e-commerce or B2B platforms. It changes frequently, has a clear business boundary, and its performance directly affects revenue — which means your team will have both the mandate and the metrics to validate the migration.
Discovery and inventory
- List every endpoint the checkout flow touches:
POST /orders,GET /orders/{id},POST /orders/{id}/payment, and any internal service calls the monolith makes during order creation. - Identify all database tables the checkout flow reads or writes. Note which tables are shared with other capabilities (e.g., a
customerstable also used by the account management module). - Measure request volume and latency baselines for each endpoint over the past 30 days.
Build and parallel run
- Build the Order service with its own database schema. For shared tables (e.g.,
customers), use the legacy read API strategy initially: call the monolith’s customer endpoint rather than copying the table. - Implement the transactional outbox pattern for order writes so the legacy
orderstable stays synchronized during the parallel run. - Configure the facade to shadow all checkout traffic to the new Order service. Run the comparator for several business days, covering at least one peak traffic period.
- Review comparator diffs daily. Common divergences: timestamp precision differences, legacy null defaults that the new service handles differently, and currency rounding in tax calculations.
Incremental cutover
- Switch read traffic for
GET /orders/{id}to the new service at 10% canary. Hold for 24 hours, review error rates and latency. - Ramp reads to 100% over three days. Confirm data reconciliation jobs show zero discrepancies.
- Cut over write traffic (
POST /orders) using the same canary ramp. Keep the legacy write path live for a short rollback period post-cutover. - After the rollback window closes with no incidents, disable the legacy checkout code path and remove the outbox sync job.
- Schedule schema cleanup: drop legacy
orderstable columns that the new service no longer writes, and remove the facade routing rules for the old paths.
Testing checklist for this slice:
- Functional: end-to-end order creation, payment processing, and order retrieval against both systems during parallel run.
- Performance: p95 latency for
POST /ordersmust be within 10% of the legacy baseline. - Data reconciliation: nightly job comparing order counts, totals, and statuses between legacy and new data stores.
- Rollback drill: execute a rollback from 10% canary before the production cutover to confirm the runbook works.
How the Strangler approach compares to the alternatives
Three alternatives come up in most architecture reviews.
Big-bang rewrite delivers the cleanest architecture but carries the highest risk. The new system must be feature-complete and fully tested before any user sees it, which means months or years of parallel development with no production validation. The failure rate is high enough that most experienced architects treat it as a last resort, reserved for systems so broken that incremental extraction is genuinely impossible.
Lift-and-shift to containers moves the monolith into Docker or Kubernetes without changing its internal structure. It solves operational problems (consistent environments, easier scaling) but does nothing for the underlying coupling. It is a useful first step that can coexist with a Strangler migration, but it is not a modernization strategy on its own.
Strangler-lite (thin facade, no data split) introduces the routing layer and extracts a few services but leaves the database shared. It delivers early wins and is appropriate when the team needs to demonstrate value quickly. The risk is that without a data split plan, the migration stalls once it hits the first capability with complex shared data.
| Approach | Risk reduction | Time to value | Complexity | Data difficulty | Team skills |
|---|---|---|---|---|---|
| Big-bang rewrite | Low (high execution risk) | Very slow | Very high | High | Full-stack rebuild |
| Lift-and-shift | Medium (ops only) | Fast | Low | None | DevOps, containers |
| Strangler-lite | Medium | Medium | Medium | Low initially | Routing, service design |
| Full Strangler migration | High | Medium-slow | High | Very high | Distributed systems, DBA, DevOps |
The system migration strategy decision ultimately comes down to three variables: how much risk the business can absorb, how much time it has, and whether the team has the distributed systems skills to manage the operational complexity of a full migration.
How Golden Path Digital runs Strangler migrations
Golden Path Digital’s approach starts with dependency mapping before any code changes. The reason is practical: teams that skip the inventory phase discover mid-migration that a “simple” capability shares a table with six others, and what looked like a two-week slice becomes a three-month data project.
The engagement model follows three phases:
Assessment: Golden Path Digital’s IBM i modernization assessment service maps the full dependency graph of your codebase before a single line is moved. For IBM i RPG environments, AS/Forward parses the codebase and surfaces call chains, data dependencies, and dead code that manual review would miss. For Laravel applications, Laravel Ascend automates framework upgrade steps from version 6 through 11, reducing the technical debt that accumulates during a long migration.
Pilot slice: A single, well-bounded capability is extracted end-to-end, including facade setup, ACL implementation, shadow traffic, and decommission. The pilot validates the team’s toolchain, surfaces data surprises early, and produces a repeatable playbook for subsequent slices.
Full run: Subsequent slices follow the playbook with decreasing external support as the internal team builds confidence. QuantaPath AI supports workflow automation and CRM integration for teams that need to modernize operational processes alongside the technical migration.
The signal to bring in an external partner is straightforward: if your team has not run a Strangler migration before, the pilot slice is where the most expensive mistakes happen. Getting the facade architecture, the data sync strategy, and the comparator tooling right on the first slice pays for itself across every subsequent extraction.
Key Takeaways
The Strangler Fig pattern is the lowest-risk path for migrating a large legacy monolith to microservices, but only when your team treats data disentanglement and active decommissioning as first-class deliverables, not afterthoughts.
| Point | Details |
|---|---|
| Facade is permanent infrastructure | Build the routing facade to last; it becomes your traffic control plane for all future extractions and canary deployments. |
| Data is the long pole | Shared schemas and cross-table joins consume more time than service code; plan the data strategy before the first slice starts. |
| Decommission is mandatory | Set a hard deadline for legacy code deletion at the start of each slice; teams that skip this end up with a distributed monolith. |
| Slice by business capability | Start with the most-changed, highest-leverage capability so future feature work flows into the new system immediately. |
| Golden Path Digital’s approach | Golden Path Digital runs dependency mapping first via AS/Forward and a structured pilot slice, reducing migration risk before full-scale extraction begins. |
The part most migration plans get wrong
Most Strangler migration plans fail not because the architecture is wrong, but because the organization treats it as a purely technical project. The facade gets built, the first two slices go smoothly, and then the migration stalls. The reason is almost always the same: no one owns the decommissioning deadline, the shared database grows more coupled with each passing sprint, and the team’s attention drifts to new feature work.
The practical rules of thumb that experienced architects follow: always own the facade as production infrastructure, never let a slice ship without a scheduled decommission date, and treat every migration step as reversible until the rollback window closes. The parallel run is not optional — it is the only mechanism that catches the behavioral differences that test suites miss, particularly in legacy systems where the “correct” behavior is whatever the old code did, including its bugs.
The deeper issue is that Strangler migrations require organizational commitment, not just engineering skill. Leadership must protect the migration budget across multiple quarters, even when the business is pushing for new features. Teams that get this right treat each extracted slice as a shipped product, complete with its own retrospective and a formal decommission sign-off. Teams that don’t end up maintaining two systems indefinitely.
The legacy code modernization discipline is ultimately about governance as much as architecture. The pattern gives you the technical framework. The governance gives you the finish line.
Golden Path Digital can map your migration before you move a line of code
If your team is planning a Strangler migration and the dependency map is still a whiteboard sketch, that is the highest-risk point in the project. Golden Path Digital’s assessment service produces a verified dependency graph of your codebase, identifies the highest-leverage first slice, and delivers a migration playbook your team can execute with confidence.

For IBM i RPG environments, AS/Forward parses decades of accumulated code and surfaces the call chains and data ownership boundaries that manual review misses. For Laravel teams, Laravel Ascend handles the framework upgrade steps that would otherwise consume weeks of developer time before the migration even starts. The result is a migration that runs on a schedule instead of on a prayer.
Ready to run a structured pilot? Start with a legacy code modernization assessment and get a clear picture of your migration scope before committing to a full extraction plan.
Useful sources and further reading
The following references are the canonical sources for the Strangler Fig pattern. Cite them in the order listed when you need authoritative backing for definition, implementation guidance, or data strategy claims.
- Strangler Fig Application — Martin Fowler: The original definition of the pattern. Cite this for the concept’s origin, the routing facade requirement, and the incremental replacement principle.
- Strangler Fig Pattern — Microsoft Azure Architecture Center: The most detailed implementation reference, covering facade introduction, ACL guidance, phased decomposition, and suitability signals. Use for core components and when-to-use criteria.
- The Strangler Fig Pattern: Migrating Legacy Monoliths — Usama Qamar — Practitioner-level guidance on shadow traffic, response diffing, and reversible cutovers. Use for implementation steps and the real-world walkthrough.
- Monolith to Microservices Migration Strategies — CircleCI: Data strategy coverage including CDC, outbox pattern, and full DB split trade-offs. Use for the data strategies section.
- The Pros and Cons of the Strangler Architecture Pattern — Red Hat Blog: Pitfalls coverage, adapter complexity warnings, and the decommissioning governance problem. Use for the common pitfalls section.
FAQ
What does the Strangler pattern mean in software architecture?
The Strangler pattern, formally called the Strangler Fig pattern, is an incremental migration strategy where a facade intercepts all traffic to a legacy system and routes it slice-by-slice to new services until the legacy system can be decommissioned. Martin Fowler coined the term, drawing the analogy from a strangler fig tree that grows around a host tree and eventually replaces it.
What is a Strangler Fig migration?
A Strangler Fig migration is the practical application of the pattern: you introduce a routing facade in front of a monolith, extract one business capability at a time into a new service, validate behavior with shadow traffic and comparators, then cut over and decommission the legacy code path. The Microsoft Azure Architecture Center documents the full phase sequence from facade introduction through final decommissioning.
How do you implement the Strangler pattern?
Start with a dependency inventory of all endpoints and data ownership, then introduce a reverse proxy or API gateway as the facade. Extract the most-changed business capability first, run shadow traffic to compare responses, migrate reads then writes using a canary ramp, and delete the legacy code path once the rollback window closes. Repeat for each subsequent capability.
Are strangler figs considered invasive?
In ecology, yes: strangler figs (genus Ficus) are considered invasive in some regions outside their native range because they grow around host trees and can eventually kill them. The software pattern borrows this metaphor intentionally — the new system grows around the legacy one until the legacy is no longer needed and can be removed.
When should you not use the Strangler pattern?
Avoid the Strangler approach when you cannot intercept traffic at the network layer, when you have no access to the legacy source code, or when the system is small enough that a clean rewrite is faster than building and maintaining a facade. The Azure Architecture Center explicitly lists these as exclusion signals.