Strangler Pattern Refactor — Refactoring Patterns, Part 10
Refactoring Patterns · Part 10
The instinct with a legacy system everyone hates is to rewrite it from scratch — and that big-bang rewrite is where projects go to die, because you're rebuilding a moving target while it keeps changing underneath you. The strangler pattern replaces it piece by piece instead, routing traffic to new code one boundary at a time until the old system can be retired. This walks through doing it without a risky flag day.
Big rewrites die. Strangler replaces a system piece by piece while it keeps running.
Step 1: The Metaphor (15 min)
Strangler fig grows around tree; eventually tree dies; fig remains.
In code:
New system grows alongside legacy
Pieces migrate over time
Legacy shrinks
Eventually retired
Step 2: Why Not Big Bang (15 min)
Rewrite from scratch:
Long time without value
Risk: never finishes
Risk: misses old features
Business halts during transition
Most big rewrites: fail or hugely delayed.
Step 3: Identify Boundaries (15 min)
Find seams in legacy:
HTTP endpoints
Module boundaries
Database tables
User-visible features
Each becomes potential migration unit.
Step 4: Route Per Boundary (15 min)
Proxy / router decides:
Request → router →
/api/v1/users → legacy
/api/v1/orders → new system
/api/v1/products → legacy
Migrate route by route.
Step 5: Feature Flag Approach (15 min)
if (flag('new-order-flow', user)) {
return newOrderService.create(req)
}
return legacyOrderService.create(req)
Gradual rollout per user. A/B test old vs new.
Step 6: Database Strangling (15 min)
Two systems writing same data:
Dual-write (both DBs)
Backfill old data
Verify consistency
Cut over reads
Stop writes to old
Slow. Careful. Months.
Step 7: Parity Tests (15 min)
For each migrated piece:
Same input to both old + new
Compare outputs
Investigate differences
Promote new when matched
Tools: shadow mode.
Step 8: Don't Drift (15 min)
Legacy still in use; bug fixes / features needed?
Apply to both
Or hold features until migration done
Don't let legacy diverge from new while migration in flight
Step 9: Track Progress (15 min)
Visible:
% of traffic on new
% of features migrated
Lines of code in legacy (going down)
Time-to-completion estimate
Without visibility: migration drags forever.
Step 10: Retire (15 min)
When 100% on new:
Delete legacy code
Drop old DB tables (after grace period)
Decommission infra
Celebrate
Document learnings
Many migrations stop at 95%. Push to 100%.
What You Just Did
Strangler pattern refactor: the metaphor, why not big bang, identify boundaries, route per boundary, feature flag approach, database strangling, parity tests, don't drift, track progress, retire.
Common Failure Modes
Big bang anyway. Often fails.
No boundaries identified. Where to start?
Diverging legacy + new. Drift accumulates.
Stop at 95%. Two systems forever.
No parity testing. Quality regression.
Continue the Refactoring Patterns path
Previous — Part 9: Refactor to Tests
Part of the Refactoring Patterns learning path.


