The strangler fig pattern is a strategy for incrementally replacing a legacy system with a new one. Named after the strangler fig plant that grows around a host tree and eventually replaces it, this pattern allows you to migrate functionality piece by piece with minimal risk and zero downtime.
Why Not a Big Bang Rewrite?
The traditional approach to legacy system replacement is the "big bang" rewrite: build the new system from scratch, then switch over in a single deployment. This approach has a terrible track record. Projects take longer than expected, fail to capture all the legacy system's behavior, and the switchover introduces immense risk.
The strangler fig pattern avoids these problems by replacing the system incrementally, one piece at a time.
How It Works
The strangler fig pattern typically involves three components:
2. **The legacy system** that continues to run.
3. **The new system** that gradually takes over functionality.
![Diagram: User -> Proxy -> either Legacy or New depending on migrated routes]
When a request arrives:
Implementation Approaches
URL Routing
Use a reverse proxy (NGINX, HAProxy, API Gateway) to route traffic based on URL patterns:
# Initially: all traffic goes to legacy
location / {
proxy_pass http://legacy-system;
}
# After migrating orders:
location /api/orders {
proxy_pass http://new-system;
}
location / {
proxy_pass http://legacy-system;
}
This is the simplest approach. New feature development happens on the new system. Legacy routes are progressively migrated.
Feature Flags
Use feature flags to control migration at a more granular level:
if (featureFlags.isEnabled('new-checkout')) {
return renderNewCheckout(data);
} else {
return proxyToLegacy(data);
}
Feature flags allow you to:
Parallel Run
For high-risk migrations, run both systems simultaneously and compare results:
2. Return the legacy system's response to the user.
3. Compare the new system's response to detect discrepancies.
4. Fix issues until responses match consistently.
5. Switch to the new system.
This is the safest approach and is commonly used for financial systems, inventory management, and other correctness-critical domains.
Data Migration
Data migration is often the hardest part. Strategies include:
**Lazy migration:** When the new system needs data that exists only in the legacy system, it copies it on demand. The first time a user accesses a migrated feature, their data is migrated.
**Bulk migration:** Copy all data to the new system before cutting over. This requires data transformation and reconciliation.
**Dual writes:** Write to both systems for a period. The new system's data may need to be backfilled from the legacy system.
**Database strangler:** Use database views, triggers, or a change data capture (CDC) pipeline to keep the new system's database in sync with the legacy system.
Choose the approach based on data volume, the cost of inconsistency, and the complexity of data transformation.
Benefits
**Reduced risk.** Each migration step is small and reversible. If something goes wrong, you roll back one feature, not the entire system.
**Continuous delivery.** The new system can be deployed incrementally. Teams get early feedback and can adjust course.
**Business continuity.** The legacy system remains operational throughout the migration. No downtime is required.
**Knowledge preservation.** Team members learn the legacy system gradually while building the new one. Domain knowledge is transferred naturally.
Challenges
**Increased complexity.** The system is now running two architectures simultaneously. Developers need to understand both.
**Performance overhead.** Routing through a proxy adds latency. Running both systems in parallel doubles infrastructure costs.
**Coordination.** Multiple teams may be migrating different features. Coordination is needed to avoid conflicts.
**Legacy data dependencies.** Some data is deeply intertwined. Features that share data are harder to migrate independently.
When to Use
Use the strangler fig pattern when:
Do not use it when:
Summary
The strangler fig pattern is the safest and most practical approach to legacy system migration. Use an intercepting proxy or feature flags to gradually route traffic from the legacy system to the new one. Migrate data lazily or in bulk depending on your requirements. Run both systems in parallel for high-risk migrations. The goal is not to replace the system quickly, but to replace it safely.