Digital Transformation
Legacy Modernization

The strangler fig pattern: the right way to modernize legacy systems without a big bang rewrite

strangler fig pattern

A practical guide to incremental legacy migration — from theory and real-world case studies to Kubernetes-native implementation on AWS, GCP, and Azure.

74% of enterprises still run business-critical monoliths
faster time-to-production with incremental migration
60% lower migration risk vs. full rewrites (Gartner)
50+ legacy modernizations delivered by Gart Solutions

Why “just rewrite it” is almost always the wrong answer

Every engineering team has had the conversation. The legacy system is slow, fragile, impossible to test, and held together by tribal knowledge and copy-pasted SQL queries from 2009. The answer seems obvious: burn it down and start fresh.

Joel Spolsky famously called this the single worst strategic mistake a software company can make. He was right then, and the data backs him up today. The FBI’s Sentinel project — a full rewrite of its case management system — ran four years late and $405 million over budget. Hershey’s ERP migration caused a 19% drop in quarterly sales. Healthcare.gov’s launch failure cost $840 million.

The core problem with big-bang rewrites is that you are simultaneously trying to replicate existing behavior (which is poorly documented and poorly understood), introduce architectural change, and ship new features — while delivering zero business value for months or years.

The strangler fig pattern offers a structurally different approach: migrate incrementally, stay in production the entire time, and let the new system grow around the old one until the legacy code can be safely removed.

The strangler fig is not a workaround or a compromise. It is the architecturally correct way to migrate a complex system under real business constraints.

Fedir Kompaniiets, CEO & Co-Founder, Gart Solutions

What is the strangler fig pattern?

The term was coined by Martin Fowler in 2004, inspired by a species of tropical fig tree that germinates in the forest canopy, wraps itself around its host tree, and eventually replaces it entirely as the host dies and rots away.

In software architecture, the pattern works the same way. A new system grows alongside the existing one. A routing layer — called the facade — sits in front of both systems and controls which requests go where. Over time, functionality is extracted from the legacy system, implemented as independent services, and traffic is redirected. When all functionality has been migrated, the legacy system is decommissioned.

Strangler fig pattern — routing architecture
Routing facade (API Gateway / reverse proxy / service mesh) Intercepts all traffic · Routes by feature flag, path, or header · Zero downtime
Still running
Legacy monolith
Handles routes not yet migrated. Receives declining share of traffic over time.
Actively growing
New microservices
Each service owns one bounded context. Independently deployable and observable.

The three defining properties of the strangler fig pattern are:

  • Facade-first: all client traffic passes through a single routing layer before touching either system.
  • Incremental by design: each migration step is a self-contained unit with its own rollback path.
  • Value-continuous: the system stays in production, revenue-generating, and fully observable throughout the entire migration.

The three phases of a strangler fig migration

Phase 01

Transform

Identify bounded contexts. Build the facade layer. Instrument the legacy system with observability tooling so you have a baseline.

Phase 02

Co-exist

Extract modules one by one. The facade routes traffic to the new service. Legacy remains hot as a fallback. Canary-test each extraction.

Phase 03

Eliminate

Once traffic for a module reaches 100% on the new service and stability is confirmed, remove the legacy code path. Rinse, repeat.

Step-by-step implementation flow

Implementation steps — left to right
1
Map the monolith

Domain model, data dependencies, inbound/outbound traffic patterns

2
Deploy the facade

API Gateway, Nginx, Envoy, or service mesh in front of everything

3
Extract first module

Lowest-risk bounded context first. Build, test, canary release

4
Shift traffic

Feature flags or weighted routing. Monitor latency, error rate, business KPIs

5
Delete legacy path

Confirm stability for 2+ weeks, then remove dead code from monolith

Choosing your migration starting point

One of the most common mistakes teams make is starting with the highest-value or highest-complexity module. This is backwards. The correct approach is to identify a strangling candidate using three criteria:

Criterion What to look for Why it matters
Low data coupling Module owns its own tables or can be easily partitioned Avoids the distributed data problem from day one
Clear API boundary Well-defined inputs and outputs, minimal hidden side effects Makes the facade routing rules simple and safe
High change frequency Module changes often, is a drag on release velocity Fastest business ROI on the migration effort
Low transaction criticality A failure here does not take down revenue flow Limits blast radius while the team builds migration muscle

Gart recommendation: At Gart Solutions, we start every engagement with a 2-week “Architecture Discovery Sprint” — mapping data flows, API contracts, and change frequency across the entire monolith before a single line of new code is written. This produces a prioritized migration backlog grounded in real risk and business impact data.

The facade layer: your most important architectural decision

The facade is the heart of the strangler fig. It must be able to route traffic, enforce contracts between old and new systems, and do so without becoming a bottleneck or a single point of failure. The right choice depends on your cloud environment and existing infrastructure.

AWS

Amazon API Gateway + Lambda authorizers + Application Load Balancer. Use weighted target groups for canary routing. Integrates natively with Route 53, CloudWatch, and X-Ray.

GCP

Apigee API Management or Cloud Endpoints with Traffic Director. Use traffic splitting policies at the load balancer level for percentage-based migration.

Azure

Azure API Management (APIM) with policy-based routing. Combine with Azure Front Door for global traffic distribution and A/B routing between legacy and new backends.

Kubernetes-Native

Istio or Linkerd service mesh with VirtualService traffic weights. Works across all clouds. Fine-grained canary control down to individual header values.

Implementation example: Kubernetes + Istio

Here is a minimal but production-representative example of routing 10% of traffic for a /api/orders endpoint to a new microservice while leaving 90% on the legacy monolith — the classic first step in a strangler fig migration.

# VirtualService: strangler fig routing rule
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: orders-strangler
spec:
  hosts:
    - orders.internal
  http:
    - match:
        - uri:
            prefix: "/api/orders"
      route:
        - destination:
            host: orders-service-new   # new microservice
            port:
              number: 8080
          weight: 10                 # 10% canary
        - destination:
            host: monolith-service     # legacy fallback
            port:
              number: 8080
          weight: 90                 # 90% baseline
    - route:
        - destination:
            host: monolith-service     # all other routes → legacy

When metrics confirm that the new service is healthy — latency within SLA, error rate below threshold, business KPIs unchanged — you increase the weight to 25%, then 50%, then 100%. At 100%, you update the VirtualService to remove the monolith destination entirely, then clean up the dead code in the next sprint.

Key insight: never adjust traffic weights faster than your observability pipeline can confirm stability. At Gart Solutions we use a minimum 72-hour soak period at each weight increment for stateful services — longer for anything touching financial transactions or user identity.

Data migration: the hardest part nobody talks about

The routing layer is the visible part. Data migration is where strangler fig projects actually succeed or fail. A monolith typically has a single, shared, highly denormalized database that every module reads and writes. Splitting this into per-service datastores requires a deliberate strategy.

The dual-write pattern

During the co-existence phase, the new service writes to its own datastore and to the legacy database. The legacy monolith continues to read from the same tables it always did. This maintains consistency during the transition without requiring a cutover event.

Event sourcing for audit trails

For complex domains, consider using an event bus (Apache Kafka, AWS EventBridge, GCP Pub/Sub) to decouple read and write paths. The monolith publishes domain events; the new service consumes them and builds its own read model. This is particularly powerful for migrating reporting and analytics modules, where eventual consistency is acceptable.

Anti-pattern warning: do not share a database between the legacy monolith and a “new” microservice. This is the most common way strangler fig migrations fail — you have built two deployment units but still have one logical system, with all the coupling that implies.

Strangler fig pattern vs. other migration strategies

Strategy Risk Level Time to Value Best for
Big-bang rewrite Very high 12–36 months Greenfield replacements with full control over timeline
Lift-and-shift Low 1–3 months Cloud cost reduction only — no modernization value
Branch-by-abstraction Medium 2–4 months In-process refactoring where a facade is impractical
Strangler fig pattern Low–medium 4–8 weeks Most enterprise legacy migrations under business continuity constraints

When the strangler fig pattern is not the right choice

The pattern is powerful, but it is not universal. There are cases where it is the wrong tool:

  • Tightly coupled UIs: server-side rendered monoliths where the frontend and backend are inseparable are significantly harder to strangle. Consider a micro-frontend layer first.
  • Batch-first systems: if the monolith is primarily a nightly batch processing system rather than a request/response service, a facade-based routing approach has limited applicability.
  • Systems requiring complete domain redesign: if the legacy system’s domain model is fundamentally broken — not just the implementation — you may need to design the new model first before any migration approach can succeed.

Real-world implementation: what a Gart Solutions engagement looks like

Over eight years and more than 50 enterprise modernization engagements, we have refined a delivery framework that consistently reduces migration risk and accelerates time to value. Here is what a typical strangler fig engagement looks like with our team.

Weeks 1–2

Architecture Discovery

Codebase analysis, dependency mapping, API contract extraction, domain model reconstruction, risk scoring of each module.

Weeks 3–6

Facade & First Module

Deploy routing infrastructure. Extract the first low-risk module as an independent service. First canary release into production.

Ongoing

Iterative Extraction

2-week sprints per module. Full observability dashboards. Knowledge transfer to your team throughout, not at the end.

We work embedded within your engineering team — not as a separate delivery unit operating in isolation. Every architectural decision is documented, every migration script is reviewed, and every new service is handed over with runbooks and ownership clearly assigned to your engineers.

Gart Solutions · Cloud Services

Ready to strangle your legacy system — safely?

Gart Solutions specializes in cloud-native architecture, Kubernetes infrastructure, and enterprise legacy modernization. We have delivered 50+ strangler fig and microservices migrations.

Legacy modernization Kubernetes & DevOps Cloud architecture Microservices design Architecture audits
Book a free architecture consultation →

Measuring success: the KPIs that actually matter

A strangler fig migration is not complete when the last line of legacy code is deleted. It is complete when the new system demonstrably performs better across the metrics that matter to the business. Track these from day one:

DORA Deployment frequency, lead time, change failure rate, MTTR

Baseline agility metrics to ensure migration doesn’t slow down delivery.

p99 Tail latency per service — catch regressions before customers do

Ensures the extra network hop in the facade doesn’t degrade user experience.

$$$ Infrastructure cost per transaction — the real ROI signal

Tracks the efficiency of the new microservices architecture vs. the old monolith.

SLO Error budget burn rate — are you more reliable post-migration?

The ultimate proof of stability during the “co-exist” phase.

Conclusion: the strangler fig pattern is not a pattern, it is a discipline

The strangler fig pattern is deceptively simple to describe and genuinely difficult to execute well. The routing facade is straightforward to build. The hard parts — identifying correct bounded contexts, managing shared data during transition, maintaining team alignment across months of incremental work — require experience, discipline, and a clear migration philosophy.

The pattern works because it respects reality: your system is in production, your users are real, and your engineering team has other work to do. It does not ask for a heroic six-month freeze; it fits into your existing sprint cadence and delivers measurable improvement every two weeks.

At Gart Solutions, we have seen the strangler fig pattern reduce deployment risk by an order of magnitude compared to big-bang rewrites — and we have the delivery track record to prove it. If your team is staring at a legacy monolith and wondering how to begin, the answer is almost always the same: start with the facade, extract the smallest safe module, and let the new system grow.

Let’s work together!

See how we can help to overcome your challenges

FAQ

How do we handle user sessions between the old and new systems?

The most robust approach is to externalize session management. Before starting the migration, move session data to a shared store like Redis. Both the legacy monolith and the new microservices can then validate the same session token, ensuring a seamless user experience without requiring users to log in again when they hit a "strangled" route.

Won’t the routing facade add significant latency to our requests?

When using cloud-native tools like AWS API Gateway, NGINX, or Istio, the overhead is typically in the low milliseconds (sub-5ms). For 99% of business applications, this is negligible compared to the architectural benefits of decoupling and the performance gains achieved by the new, optimized microservices.

What happens if a newly extracted module fails in production?

This is the primary safety benefit of the Strangler Fig. Because the facade controls traffic weights, a rollback is near-instant. You simply update the routing configuration to send 100% of traffic back to the legacy monolith. There is no need for a complex code redeploy or database restoration in the middle of an incident.

How do you prevent "Distributed Monolith" syndrome during migration?

We strictly enforce Data Sovereignty. If a service is extracted, it must own its data. If a new service relies on the monolith’s database for every request, you haven't modernized; you’ve just added network latency. We use the Dual-Write or Change Data Capture (CDC) patterns to sync data safely during the transition.
arrow arrow

Thank you
for contacting us!

Please, check your email

arrow arrow

Thank you

You've been subscribed

We use cookies to enhance your browsing experience. By clicking "Accept," you consent to the use of cookies. To learn more, read our Privacy Policy