Java

Strangler Fig Pattern

The Strangler Fig pattern enables gradual migration from legacy systems to new implementations. Named after the strangler fig tree that grows around its host, this pattern lets you incrementally replace functionality while keeping the system running.

📋 At a Glance

AspectDetails
OriginMartin Fowler, 2004
Use CaseMigrating from legacy to modern systems
Key BenefitContinuous operation during migration
Risk LevelLow (incremental changes)

🎯 What You'll Learn

  • Strangler Fig pattern implementation
  • Feature toggles for gradual rollout
  • Request routing strategies
  • Data synchronization during migration
  • Rollback strategies when things go wrong

Production Story: The Monolith Migration

A company needed to migrate from a legacy Java 6 monolith to microservices:

Risky approach (rejected):
TEXT(5 lines)
Code
Loading syntax highlighter...
Strangler Fig approach:
TEXT(7 lines)
Code
Loading syntax highlighter...

Mental Model: Strangler Fig

TEXT(34 lines)
Code
Loading syntax highlighter...

🔬 Deep Dive

Pattern 1: Proxy-Based Strangler

JAVA(42 lines)
Code
Loading syntax highlighter...

Pattern 2: Feature Toggle Service

JAVA(57 lines)
Code
Loading syntax highlighter...

Pattern 3: Parallel Run Verification

JAVA(54 lines)
Code
Loading syntax highlighter...

Pattern 4: Data Synchronization

JAVA(75 lines)
Code
Loading syntax highlighter...

Pattern 5: Rollback Strategy

JAVA(62 lines)
Code
Loading syntax highlighter...

Pattern 6: Event-Based Strangler

JAVA(47 lines)
Code
Loading syntax highlighter...

Migration Checklist

TEXT(26 lines)
Code
Loading syntax highlighter...

🐛 Debug This: The Data Divergence

A team is migrating their order system using the Strangler Fig pattern. They set up dual-write to both legacy and new databases. After a week, they notice the new system reports different revenue totals. "We're writing to both systems - how can the data be different?"

JAVA(62 lines)
Code
Loading syntax highlighter...
After a week, the new system shows $50,000 less revenue. What's wrong?

✅ Solution:

Multiple data synchronization bugs:

Problem 1: Total calculated differently
JAVA(5 lines)
Code
Loading syntax highlighter...
If request.getTotal() is null, 0, or different from calculated, data diverges.
Problem 2: Missing initial data migration

The code only handles new orders. What about orders created before dual-write was enabled? They exist in legacy but not in new system.

Problem 3: Race condition in status update
JAVA(2 lines)
Code
Loading syntax highlighter...

If the new order hasn't synced yet (dual-write just enabled), status update is silently skipped.

Problem 4: No error handling

If new system write fails, the error is swallowed (from earlier code review - try/catch with just logging).

Correct implementation:
JAVA(82 lines)
Code
Loading syntax highlighter...
The lesson: In dual-write scenarios: (1) use the same calculated values for both systems, (2) handle missing records, (3) verify consistency continuously, (4) have a resync mechanism.

💻 Exercises

Exercise 1: Basic Feature Toggle

⭐ Difficulty: Easy | ⏱️ Time: 10 minutes

Task: Implement a feature toggle service that supports percentage-based rollout with consistent hashing.
JAVA(4 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(66 lines)
Code
Loading syntax highlighter...

Exercise 2: Proxy Router

⭐⭐ Difficulty: Medium | ⏱️ Time: 15 minutes

Task: Implement a proxy that routes requests to either legacy or new service based on feature toggles.
JAVA(5 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(119 lines)
Code
Loading syntax highlighter...

Exercise 3: Parallel Run Comparator

⭐⭐ Difficulty: Medium | ⏱️ Time: 20 minutes

Task: Implement parallel run that calls both systems and compares results.
JAVA(5 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(121 lines)
Code
Loading syntax highlighter...

Exercise 4: Circuit Breaker for Migration

⭐⭐⭐ Difficulty: Medium-Hard | ⏱️ Time: 20 minutes

Task: Implement a circuit breaker that automatically rolls back to legacy on errors.
JAVA(6 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(159 lines)
Code
Loading syntax highlighter...

Exercise 5: Complete Migration Orchestrator

⭐⭐⭐⭐ Difficulty: Hard | ⏱️ Time: 30 minutes

Task: Build a complete migration orchestrator that coordinates feature toggle, parallel run, circuit breaker, and data sync.
JAVA(6 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(234 lines)
Code
Loading syntax highlighter...

📝 Summary

ComponentPurpose
Proxy/FacadeRoute traffic between systems
Feature TogglesControl rollout percentage
Parallel RunVerify new matches legacy
Circuit BreakerAutomatic rollback on errors
CDC/Dual WriteKeep data synchronized

📅 Review Schedule for This Article

DayTaskTime
Day 1Review the Strangler Fig phases diagram5 min
Day 3Redo Exercise 1 (Feature Toggle)10 min
Day 7Draw a strangler fig architecture for a system you know15 min
Day 14Redo Debug This (The Data Divergence)15 min
Day 30Plan a migration using the Migration Checklist20 min

Next: [Part 23: Modern Java Clean Code]