Strangler Fig Pattern: Core Concepts
Replace a system by capability
The strangler fig pattern modernizes a legacy system incrementally. A facade, gateway, or routing boundary receives requests and directs selected capabilities to new implementations while the legacy system continues serving the rest. Each capability can be migrated, validated, and released independently. The legacy footprint shrinks over time instead of requiring a high-risk big-bang cutover.
The pattern is useful when a legacy application is difficult to replace at once, but the team can identify stable seams around routes, workflows, or data ownership. It works best when traffic can be routed predictably, the new capability can coexist with the old one, and observability can distinguish which implementation handled a request. It is not a shortcut around understanding the legacy behavior; the facade can preserve the same hidden coupling if the boundary is poorly defined.
Establish the routing seam
The facade may be a reverse proxy, API gateway, modular monolith entry point, or application-level router. It maps each request or capability to an owner and implementation. Keep routing rules explicit, tested, and version-controlled. Avoid routing by fragile payload guesses or user-specific hidden conditions unless those are deliberate and observable. A request should not be split across old and new implementations in a way that creates unclear data ownership.
Start with a low-risk vertical slice. Move a complete capability, including its data behavior, security, and operational support, rather than moving a layer of code that still depends heavily on the legacy system. Preserve external contracts where possible. If the contract must change, version or migrate consumers deliberately. Define how errors, authentication, audit records, and correlation IDs cross the facade.
Handle data and consistency
Data is often the hardest part of strangling a monolith. Decide which system is authoritative for each entity at each migration stage. Avoid uncontrolled dual writes: partial failure can leave the old and new stores inconsistent. If dual-write is unavoidable, use an outbox or another reliable capture mechanism, make operations idempotent, and build reconciliation. Read routing must know which store contains the current value; stale fallback can return incorrect data.
A migration can use expand-and-contract steps: add compatible schema, deploy code that can read old and new forms, backfill, verify, switch ownership, and later remove the old representation. Track progress and define rollback before changing authority. A proxy cannot make a destructive data migration safe by itself.
Shift traffic gradually
Route an internal cohort or small percentage first, then increase only when metrics and user outcomes remain within thresholds. Use feature flags or routing rules with clear ownership and a default. Compare error rate, latency, business outcomes, and data consistency for old and new paths. Canary by tenant or request cohort only when the cohort boundary does not violate isolation or fairness.
Rollback should be tested and may change over time. Before data ownership moves, traffic can often return to the old implementation. After irreversible writes or schema changes, rollback may require a forward fix or reconciliation. Document the rollback boundary and stop condition. Maintain the facade until all traffic and consumers have moved, then remove obsolete routes, credentials, data paths, and legacy code. A permanent routing layer with duplicate implementations is not a completed strangler migration.
Strangler Fig Pattern: Practice
Migrate customer profile reads
Suppose a monolith serves customer profiles, account settings, and billing history. The team wants a new profile service but cannot stop feature delivery for a year-long rewrite. Begin by mapping routes, data ownership, dependencies, traffic, and current behavior. Select profile reads as a first slice only if their contract and data sources can be separated without changing billing or account invariants.
Place a facade in front of the existing routes. Initially, all profile traffic continues to the monolith, proving that the new routing layer preserves authentication, headers, status codes, and observability. Add the new service behind the same contract and run it against a controlled cohort. Compare normalized responses and latency, while ensuring logs do not expose profile data. Do not send production writes to both systems merely to compare results.
Define authority and rollout
Before shifting reads, specify which store owns profile data and how changes made in the monolith reach the new service. A change-data stream or outbox may keep the new read model current, but lag must be measured and represented in the contract. If the new service becomes authoritative for writes, migrate ownership in an explicit step and prevent both systems from accepting conflicting updates.
Start with internal users or a small tenant cohort. Define thresholds for error rate, p95 latency, stale-read rate, and support impact. Increase exposure in stages. Make the flag or route configuration observable and ensure the on-call engineer can route traffic back. Rehearse the switch before an incident; an untested rollback is only an assumption.
Address failure and security
If the new service is unavailable, decide whether reads can safely fall back to the monolith. A fallback can improve availability but may return stale or inconsistent data after ownership moves. Restrict fallback to a period when the legacy data is known to be current, and measure it. Avoid retry loops between facade and services. Propagate identity and authorization context securely, and enforce resource permissions in the new service rather than trusting the gateway alone.
Track which implementation handles each request, but use low-cardinality metrics and avoid customer identifiers as labels. Correlate traces across the facade, old application, and new service. Alert on route distribution, errors, latency, replication lag, and fallback rate. Update the service catalog and runbook so operators know which team owns each capability.
Complete the migration
After the new service meets thresholds, move all supported traffic and verify consumers no longer call legacy paths. Remove old routes, flags, adapters, database permissions, and unused credentials. Archive or delete old data according to retention and audit requirements. Update diagrams and ADRs to show the final ownership boundary. Do not leave a permanent dual path just because the cleanup is less exciting than the migration.
Exercise a failure at each stage: route to the legacy path, route to the new path, lose the replication stream, and attempt rollback after data ownership changes. Record what can be reversed and what requires a forward repair. The strangler pattern succeeds through small independently verifiable steps with explicit authority, not merely by proxying traffic between two codebases.
Strangler Fig Pattern: Trade-offs and Interviews
Incremental delivery adds temporary complexity
The strangler pattern avoids a single cutover but temporarily requires two implementations, a routing boundary, compatibility behavior, and possibly data synchronization. The transition can be more complex than the final architecture. Budget for that work and define a removal condition. If the legacy system is small, well-tested, and replaceable in one controlled release, a direct replacement may be safer and cheaper.
The pattern also depends on finding a meaningful seam. A route-level facade is insufficient if every new capability must still read and write tightly coupled tables in the monolith. Identify data authority and dependencies before selecting a slice. If the boundary cannot be separated, first create modular seams or use branch by abstraction inside the codebase.
Protect consistency and rollback
Traffic routing and data migration are related but distinct. A request can be routed correctly while reading stale data. Define which implementation owns writes, how updates propagate, how lag is detected, and what happens when propagation fails. Avoid dual-write without an idempotency and reconciliation plan. Test rollback at each migration stage and state when rollback stops being safe.
Flags and routing rules should have owners, metrics, and expiry criteria. Temporary configuration often becomes forgotten production behavior. Track adoption by capability and remove old code, credentials, routes, and data access after cutover. The success metric is not the number of services created; it is reduced change risk and a simpler final ownership model.
Interview framing
In an interview, describe the facade, choose a vertical slice, explain how data authority moves, and show a gradual rollout with measurable thresholds. Discuss security propagation, observability, fallback, and rollback. Name the temporary complexity and the plan to remove it. If the domain is too coupled for a safe slice, explain the prerequisite work or why a different migration strategy is preferable. This demonstrates that strangler is a controlled transition pattern, not an automatic answer to every legacy system.
Set a measurable exit criterion for each slice. It might require all consumers to use the new contract, data reconciliation to remain clean for a defined period, and operational alerts to be owned by the receiving team. Track remaining legacy traffic with a metric instead of relying only on repository search. A temporary facade that has no retirement condition can outlive the migration and become an unowned dependency.
Choose migration boundaries based on business capability and data ownership. Moving a user interface first may create a new client that still depends on every legacy endpoint; moving a service layer may leave shared tables as the real coupling. Map the end-to-end write path before selecting a slice. If the boundary is not yet safe, create it through modularization or branch by abstraction before routing traffic elsewhere.
Treat the transition as a sequence of decisions. At each stage, compare observed behavior with the expected service objective, verify rollback, and update the risk register. If a slice repeatedly requires exceptions to the routing rule or cannot be reconciled, stop expanding and revisit the boundary. Continuing because the migration has already started is not a reason to accept uncontrolled data risk.
Quiz
1. Which statement about Strangler Fig Pattern is accurate?
2. When reviewing Strangler Fig Pattern, which point must hold?
3. What makes a good first slice for the strangler pattern?
4. Why is uncontrolled dual-writing risky during migration?
Flashcards
Question
What is Strangler Fig Pattern?
Click to reveal answer
Answer
Route traffic incrementally to new services while the legacy system shrinks.
Question
Strangler Fig Pattern: why it matters
Click to reveal answer
Answer
A facade intercepts requests and routes them to old or new implementations per feature.
Question
Strangler Fig Pattern: key detail
Click to reveal answer
Answer
Each strangulated capability ships independently with rollback always available.
Question
Strangler Fig Pattern: practical note
Click to reveal answer
Answer
The legacy system shrinks over releases instead of disappearing in one risky cutover.
Question
What should define a safe first strangler slice?
Click to reveal answer
Answer
A complete capability with a stable boundary and understood data ownership.
Revision Notes
Key Takeaways
- 1. A facade intercepts requests and routes them to old or new implementations per feature.
- 2. Each strangulated capability ships independently with rollback always available.
- 3. The legacy system shrinks over releases instead of disappearing in one risky cutover.
Interview Tips
- • Explain Strangler Fig Pattern with one concrete example from real modernization work, not a textbook restatement.
- • Discuss the trade-off: when Strangler Fig Pattern helps and when a lighter approach wins.
- • Place Strangler Fig Pattern inside the Integration Patterns and Legacy Modernization phase — interviewers check that you see the progression, not isolated facts.
Cheat Sheet
Strangler Fig Pattern Cheat Sheet
Phase: Integration Patterns and Legacy Modernization | Level: intermediate
Key points:
- A facade intercepts requests and routes them to old or new implementations per feature.
- Each strangulated capability ships independently with rollback always available.
- The legacy system shrinks over releases instead of disappearing in one risky cutover.
Tags: modernization, migration
Continue Learning
Before You Start
- No prerequisites listed.