Java Omnibus
OOAD & Architecture / Microservices & Distributed Patterns / Strangler Fig Pattern
Strangler Fig Migration Modernization Java
Microservices & Distributed Patterns

The safest way to modernize a large system is usually to replace one capability at a time while the old and new coexist.

Most real organizations are not starting from a clean slate. They are evolving a monolith, a legacy platform, or a tangled set of integrations. The Strangler Fig pattern supports gradual replacement by routing selected capabilities to a new implementation while the old system continues to run for the rest.

Why This Topic Matters

Why it matters in real Java systems

A big-bang rewrite of ordering or payments is rarely the responsible path for a running business. Incremental extraction lets the team learn boundary quality, production behavior, and data migration realities one capability at a time without betting the whole platform on one cutover date.

Core Explanation

The main design idea

The Strangler Fig pattern surrounds an old system with a new boundary layer, then gradually redirects requests or events to new implementations. Over time, the legacy surface shrinks until the old capability can be retired. This approach lowers migration risk and creates feedback loops that a rewrite cannot provide.

It works best when the extracted capability has a clear boundary, well-understood data ownership, and measurable traffic. It works poorly when teams try to strangler everything at once or when no one can define what the legacy system actually owns.

Concept Breakdown

Key ideas to keep in mind

Concept

Incremental replacement

Move one capability at a time instead of rewriting the whole platform.

Concept

Protective routing layer

Use adapters, proxies, or gateways to direct traffic gradually.

Concept

Learning in production

Each extraction teaches boundary quality, performance, and migration risk.

Migration sequence

Migration sequence

Step 1

Find a clean capability seam

Choose a capability with meaningful ownership and manageable integrations.

Step 2

Introduce a routing boundary

Place a façade, gateway, or event bridge in front of the old and new implementations.

Step 3

Move behavior and data deliberately

Extract rules first, then transition persistence and reporting paths carefully.

Step 4

Retire the old path

Once confidence and completeness are proven, remove the legacy capability instead of leaving both forever.

Java Example

Java example in the Order Management domain

Java example: routing a capability during extraction
package org.javaomnibus.migration;

public final class OrderRoutingFacade {
    private final LegacyOrderSystem legacyOrderSystem;
    private final NewOrderService newOrderService;

    public OrderView findById(String orderId) {
        return isMigrated(orderId)
            ? newOrderService.findById(orderId)
            : legacyOrderSystem.findById(orderId);
    }

    private boolean isMigrated(String orderId) {
        return orderId.startsWith("N-");
    }
}
Code Walkthrough

Step by step

  1. The façade lets old and new implementations coexist behind one stable caller boundary.
  2. Real migrations use more sophisticated routing logic, but the pattern is the same.
  3. The migration becomes incremental and observable instead of all-or-nothing.
  4. This is modernization through controlled replacement rather than one-shot reinvention.
Real-World Usage

Where this helps in practice

  • Modernizing monolith modules one capability at a time
  • Replacing legacy order, payment, or inventory subsystems safely
  • De-risking platform migration with progressive traffic movement
Trade-Offs

Trade-offs and when to be careful

  • Strangler Fig lowers migration risk, but it creates a temporary coexistence period that requires discipline and cleanup.
  • Teams must avoid letting temporary routing and duplicate logic become permanent architecture.
Common Mistakes

Frequent mistakes to watch for

  • Trying to strangler too many capabilities at once
  • Choosing seams that are not true business boundaries
  • Leaving dual-write and dual-read paths undocumented and unobserved
  • Never retiring the legacy path after confidence is achieved
Related Pages

Related concepts


What To Read Next