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
The default alternative is the "big rewrite": build a replacement alongside, then cut over. Big rewrites fail for known reasons -- they take longer than planned, the real legacy behavior is not as documented, users need new features during the wait, and the cutover day is a coin flip.
Strangler Fig trades a scary one-day cutover for a long series of boring small cutovers. Each one is reversible. Each one ships value independently.
Concrete Example
Monolith LegacyShop with routes /catalog, /cart, /checkout, /account.
Step 1: place a reverse proxy (or API gateway) in front of the monolith. For now, every request goes through the proxy to LegacyShop. Behavior unchanged.
Step 2: build NewCatalog (a new service). Route only /catalog/* requests to it, others still hit LegacyShop. If NewCatalog fails, proxy falls back to legacy. Users do not notice.
Step 3: build NewCart. Move /cart/* to it. Same pattern.
Step 4: /checkout depends on cart + catalog + account. Rather than move it wholesale, split it: payment capture first (the simpler sub-route), then the rest.
Step 5: once legacy LegacyShop only serves /account/*, decide: keep (the juice is not worth squeezing), or migrate it and turn the monolith off.
At each step, the system ships. The proxy is the abstraction. The migration is the fig.
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
Rules:
- Every migrated slice must be reversible at the proxy level.
- Observability comes first. You cannot strangle what you cannot measure.
- The proxy is transitional. Plan its removal if it no longer pays after the legacy is gone.
Check Yourself
- Why is a Strangler migration preferred over a big-bang rewrite for most nontrivial legacy systems?
- 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?
Video and Lecture References
- Primary lecture: Fowler -- Strangler Fig Application (text, 10-min read)
- Visual supplement: Premanand Chandrasekaran -- Embracing the Strangler Fig Pattern (20-min read)
Article References
- Fowler: Patterns of Legacy Displacement - catalog that generalizes Strangler
- Fowler: Legacy Seam - where the strangler finds its grip
- Fowler: Transitional Architecture - the "proxy is transitional" idea
External Exercises
- Interview a senior engineer on your team: what was the last Strangler-style migration they lived through? What broke?
- Fowler: Uncovering Mainframe Seams - case study with real seams
Depth Path
- Read This Only If Stuck - Fowler chunks 020-021 (Refactoring Architecture and YAGNI, Refactoring and Performance) for the "why incremental" argument
- Optional deep dive: Ian Cartwright, Rob Horn, James Lewis -- "Patterns of Legacy Displacement" series for full catalog
Source Backbone
Refactoring is the canonical book backbone for this module. Use these sources after attempting the refactor and tests yourself.
- Refactoring (Fowler) - primary source for refactoring discipline and named moves.
- Clean Code - support for readability and small-function judgment.
- Good Code, Bad Code - support for maintainability tradeoffs.