The Strangler Fig Pattern
Named after strangler fig trees that grow around a host tree and eventually replace it, this pattern lets you incrementally migrate from a monolith to microservices — without a risky "big bang" rewrite.
The Core Idea
Place a proxy in front of the monolith. Gradually route traffic for specific features to new services. The monolith shrinks over time until it's gone (or small enough to maintain).
- Each migration step is small and reversible
- The old and new systems run simultaneously
- Users never notice the transition
The Four Phases
Key Techniques
The Strangler Proxy
A reverse proxy (Nginx, Envoy, API Gateway) that routes by URL path or header:
/api/orders/*→ new Orders service/api/payments/*→ still monolith (not migrated yet)- Routing changes are config-only — no code deploys needed to shift traffic
Data Migration Strategies
- Dual-write: New service writes to both old and new DB during transition. Risk: inconsistency if one write fails.
- Change Data Capture (CDC): Stream database changes from monolith DB to new service's DB via Debezium/Kafka. Safer than dual-write.
- Database-per-service: Target state — each service owns its data. Migrate gradually using CDC, then cut over.
Feature Flags for Granular Control
- Route 1% of traffic to new service, monitor errors, ramp up
- Instant rollback: flip the flag, 100% goes back to monolith
- Canary by user segment: internal users first, then beta, then everyone
What to Migrate First?
Prioritize modules that are:
- High change frequency: Extracted service lets the team ship faster without monolith deploys
- Low coupling: Minimal data sharing with rest of monolith — cleaner extraction
- Clear boundary: Well-defined API surface — easier to put behind a proxy
- Different scaling needs: Immediate operational benefit from independent scaling
Avoid starting with: core domain (too coupled), shared auth (too cross-cutting), or anything without clear ownership.
Real-World Examples
🏢 Stripe — Ruby Monolith Migration
- Stripe's core was a large Ruby monolith processing billions in payments
- Couldn't do a big-bang rewrite — any downtime = money lost
- Used strangler pattern: new payment flows routed to new services, legacy flows remained in monolith
- Key insight: They kept the monolith for years alongside new services. "Done" doesn't mean monolith is gone — it means it's stable and shrinking.
🏢 Amazon — From Bookstore Monolith to 1000+ Services
- Early 2000s: Amazon was a monolithic C++ application
- CEO mandate: all teams must communicate via service interfaces (the famous Bezos API memo)
- Migration took years — each team extracted their domain into a service at their own pace
- No central "rewrite project" — organic, team-by-team extraction driven by pain and need
- Result: enabled AWS (internal services became external products)
Interactive: Plan Your Migration Order
You have a monolith with 5 modules. Rank them by migration priority based on their characteristics: