Incremental Strangler Refactors in Production
What This Concept Is
The Strangler Fig pattern (Martin Fowler, 2004) is a strategy for replacing a legacy system by growing a new system around it rather than rewriting it.
Metaphor: a strangler fig vine germinates in a host tree, grows around it, and gradually takes over the host's role. The replacement is not scheduled as an event; it is a process of continuous migration.
High-level activities (Cartwright / Horn / Lewis):
- Understand the outcomes you want to achieve.
- Decide how to break the problem up into smaller parts.
- Successfully deliver those parts.
- Change the organization to allow this to happen on an ongoing basis.
Mechanism: identify seams (from Cluster 2) in the legacy system, route requests through those seams, and migrate specific behaviors from legacy to new one at a time. Often an adapter or proxy lives in front of the legacy to redirect selected traffic to the new implementation.
Connection to primary concept (Branch by Abstraction & Parallel Change): Strangler Fig is typically implemented using Branch by Abstraction and Parallel Change as its internal moves. It is the system-level pattern; they are the code-level patterns.
Why It Matters Here
Incremental displacement can expose real usage and reduce the size of each cutover. It also introduces coexistence, routing and data-consistency costs. Compare it with an in-place change or bounded replacement; size alone does not choose the strategy.
Routing back is not data rollback. Once the new path writes state, changes a schema or sends an external message, the old path may be unable to interpret or undo that effect. Define the recovery boundary before migration.
Concrete Example
A shop proposes migrating catalogue reads before checkout writes. Catalogue reads still need compatible authorization, cache and freshness semantics. Shadow comparisons must use controlled read-only operations, comparable data versions and protected records.
For writes, imagine the new notification provider accepts a request and sends the message, but its acknowledgement is lost. Retrying through the old provider can send a second message. A timeout establishes an unknown outcome, not a failed effect.
The offline send lab invokes one selected provider once and propagates uncertainty. It deliberately does not solve durable deduplication or distributed transactions. A production plan needs a persisted request identity, a reconciliation source, retention and scope rules, and a stated owner for recovery. A route switch alone supplies none of those guarantees.
Common Confusion / Misconception
"Strangler means rewrite, just slowly." Not quite. Strangler means displacement: at each step behavior is moved from one implementation to another, with the proxy deciding which one runs. A rewrite-in-parallel without migration traffic is still a rewrite with a late big-bang cutover.
"The proxy is free." It is not. It is a new operational concern: monitoring, latency, failure handling. Skipping this often turns the pattern into chaos. See Fowler's Patterns of Legacy Displacement for catalog-level guidance.
"We can do this with only a code change." Strangler Fig is a sociotechnical pattern: organization, ownership, deployment, and observability all have to change. If only the code moves, the organization still reasons about the monolith.
How To Use It
Specify one bounded slice, dependencies, state authority, observations and rollout criteria. Test an acknowledgement lost after a write, a schema the old version cannot read, and a routing failure. Decide whether recovery means routing back, pausing, reconciling, compensating or rolling forward.
Record operational costs and who may authorize each action. Remove transitional components only when their compatibility and recovery roles are retired. Do not shadow or automatically retry side-effecting requests merely to compare implementations.
Check Yourself
- What evidence would favor incremental displacement, and what coexistence costs could favor another approach?
- What is the role of the proxy / adapter, and why is it both enabler and operational cost?
- How does Strangler Fig use the Cluster-2 concept of seams?
Mini Drill or Application
Pick a legacy component you work with (or any public example -- a pre-SaaS desktop app's backend, an old PHP site, a mainframe-backed banking layer). Sketch a Strangler migration plan: where is the seam, which slice migrates first, what is the observability plan, what is the rollback path, when is the old system removed?
Engineering Extension: Distinguish unknown from rejected
A provider may commit before timing out. Record the uncertainty and reconcile against the authoritative system. Idempotency depends on key scope, durable records and retention; the presence of a key argument alone establishes none of it. Prefer a recovery plan that explicitly states what it cannot roll back.
Use the behavior contracts, labs and practice feedback to test the claim.
Read This Only If Stuck
Locate this move through the Refactoring book index. The selective reading guide gives exact consulted local locators and primary documentation. Index links are not exact chapter links.