All Articles
LegacyArchitectureModernization

Strangler Fig in the Wild: Modernizing a 15-Year-Old Monolith Without a Freeze

You can replace a legacy monolith without a code freeze — if you strangle it instead of rewriting it. Here's what that actually looks like in practice.

MGMohamed Ghassen BrahimJanuary 19, 20269 min read

You can replace a 15-year-old monolith without a code freeze, without a rewrite war room, and without gambling the business on a launch date. The condition: you have to strangle it, not rebuild it.

I've run this pattern across multiple large-scale modernization programmes — including a core policy administration system at a major reinsurer that had been accumulating technical debt since 2008. The codebase was 1.4 million lines of Java. Four engineers held the full mental model. The board wanted "cloud migration." The VP of Engineering wanted to keep shipping new products without losing a quarter to a freeze.

We did both. Here's what that actually looked like.

0
Business days of code freeze
Full feature delivery continued throughout the 18-month programme
18mo
Full migration timeline
From facade installation to legacy system decommission
62%
Infrastructure cost reduction
Post-migration, compared to on-prem legacy footprint
4x
Faster feature delivery post-migration
Measured in lead time from commit to production

Why "Rewrite" Is Usually the Wrong Word

When a leadership team says "we need to modernize," what they often mean is "this system is slowing us down and we want it to stop." That's a legitimate problem. The proposed solution — a clean-sheet rewrite — is almost never the right answer for systems above a certain age and complexity.

The research on big-bang rewrites is unambiguous. They take two to three times longer than estimated. The legacy system accretes new requirements during the rewrite. The new system launches with a feature set that doesn't match the old one. Users experience regression. The rewrite team, burned out and demoralized, hands over a system that is technically newer but operationally immature.

More practically: a full rewrite requires a period where the engineering team is building the future while also supporting the present. That is not sustainable for more than a few months. At eighteen months — the minimum for a complex enterprise system — you will lose your best engineers before the finish line.

The Strangler Fig is different. You build the new system incrementally alongside the old one. Traffic routes progressively. The legacy system shrinks as the new one grows. Nobody freezes anything.

🔍

The decision that changed everything

On the reinsurer programme, the initial proposal from an external consultancy was a 24-month big-bang rewrite with a 6-month feature freeze. I recommended the Strangler Fig approach instead. The board's reaction was skepticism — "how do we know it's really being replaced?" We answered that by making the migration progress a board-level metric, visible every month. Transparency converted skepticism into alignment.

What "Strangling" Actually Requires

The Strangler Fig is not a philosophy, it's a pattern with specific mechanical requirements. Getting any of them wrong collapses the approach into something more dangerous than a rewrite.

A facade you control

The first step is installing a routing layer in front of the legacy system. This facade — an API gateway, a reverse proxy, or an application-level router — becomes the mechanism through which you selectively redirect traffic. Every user request still enters through the facade, but you now control where it exits: old system or new.

On the reinsurer programme we used Azure API Management as the facade. It added less than 3ms of latency, gave us per-endpoint routing rules, and integrated with our feature flag system so we could route by tenant, by product line, or by user segment.

The facade must be in place and transparent — zero visible change to users — before you extract a single domain. Skipping this step is the most common failure mode I see in teams that attempt this pattern.

The routing structure looks like this:

Bounded domains, not layers

The second requirement is mapping your legacy system into bounded domains before you touch any code. Not technical layers — not "the database tier" or "the service layer." Bounded domains: coherent chunks of business capability that can be reasoned about, migrated, and tested independently.

On a 1.4-million-line Java monolith, this took four weeks. We ran event-storming sessions with the four engineers who held the mental model, mapped domain boundaries against data ownership, and produced a migration priority matrix.

DomainBusiness ValueMigration ComplexityWave
User authentication and sessionMediumLow — no business logic1
Document generation and deliveryHighMedium — external integrations1
Premium calculation engineVery highVery high — 800k lines, shared DB schema4
Claims intake and routingHighMedium — clear API boundary2
Regulatory reportingMediumLow — isolated, batch-only2
Policy lifecycle managementVery highVery high — core transactional domain5
Reinsurance treaty managementVery highHigh — complex business rules3

We started with authentication — lowest complexity, established a pattern, validated the approach end-to-end with real production traffic before tackling anything consequential.

Dual-write data discipline

The hardest technical problem in a Strangler Fig is data. The legacy system has a schema that grew organically over 15 years. The new system has a schema designed for the target architecture. During the transition, both systems need to be consistent.

We used a dual-write strategy: writes went to the legacy system as primary and were replicated to the new system via an event-sourced pipeline. This kept the legacy system as the source of truth during each domain's transition period, which simplified rollback dramatically. Once a domain's reads were fully migrated to the new system, we promoted it to primary for that domain and stopped writing to the legacy schema for those entities.

⚠️

The dual-write failure mode

Dual-write is safe only if you treat the legacy system as primary until you're confident enough to cut over reads. If you attempt to make the new system the write primary too early — before all consumers are migrated — you will diverge your data and recovery is painful. We held this discipline on every domain migration. It cost time. It avoided three incidents that would have cost far more.

The Migration Programme in Practice

1
Decompose the Legacy SystemWeeks 1–4

Map the legacy system into bounded domains. These become your migration units. A bounded domain is a set of related capabilities that can be migrated together without affecting other domains.

  • Document all capabilities (user journeys, not technical functions)
  • Map capabilities to data entities and dependencies
  • Identify the boundaries between capabilities
  • Score each domain: migration complexity vs. business value
2
Install the FacadeWeeks 4–8

Deploy the routing facade in front of the legacy system. At this stage, 100% of traffic passes through to the legacy system unchanged. This establishes the mechanism for gradual migration.

  • Choose and deploy the facade technology (APIM, Front Door, NGINX)
  • Validate no latency degradation with full legacy pass-through
  • Implement traffic routing rules and feature flags
  • Establish monitoring for both systems via the facade
3
Extract High-Value, Low-Risk Domains FirstMonths 2–6

Start with domains that deliver quick wins: high business value, relatively low complexity, limited data coupling. This builds confidence, validates the approach, and delivers value early.

  • Prioritise domains with clear API boundaries
  • Avoid domains with complex shared data or transactional coupling in early waves
  • Validate new implementation against legacy in shadow mode before traffic migration
4
Migrate Core DomainsMonths 6–18

Tackle the complex, high-coupled core domains. This is the hardest phase — core domains often have the most technical debt, the most data coupling, and the highest operational risk.

  • Implement the strangler incrementally within each domain
  • Manage data migration with dual-write and careful consistency validation
  • Run the old and new implementations in parallel until confidence is high
5
Decommission the Legacy SystemFinal phase

When all traffic has been migrated and new systems are stable, decommission the legacy system. This requires confidence in the new system and a clear process for handling edge cases discovered post-decommission.

  • Gradually reduce legacy system capacity as traffic migrates
  • Keep the legacy system available (read-only) for an agreed period post-cutover
  • Formal decommission with data archival and access log retention

What the Legacy System Looks Like at Month 6

A common anxiety from engineering leaders and boards at the start of this kind of programme: "How do we know it's actually working?" The answer is measurable, not impressionistic.

By month 6 on the reinsurer programme, the dashboard showed:

  • 3 of 8 domains fully migrated to the new system, handling 100% of their traffic
  • 2 domains in parallel run (traffic split between old and new, with consistency monitoring)
  • Legacy system traffic volume down 34% from baseline
  • Zero migration-related incidents in production
  • Feature delivery in migrated domains: 3x faster than equivalent domains still in the legacy system

The velocity difference between migrated and unmigrated domains is the most persuasive data point. Once engineering leaders can see that the teams working in the new system are shipping features in days that used to take weeks, the organizational appetite for migration accelerates.

Where Teams Get This Wrong

They declare victory too early. The temptation is to migrate 70% of traffic, declare the legacy system "mostly decommissioned," and redirect the team to new product work. The remaining 30% — the hardest, most coupled core domains — gets deferred indefinitely. Two years later it's still running. Unmaintained. Increasingly risky. Set a decommission date for the legacy system and treat it as a delivery commitment.

They allow scope creep during extraction. Building a new implementation of a domain creates an irresistible invitation to also improve it. "While we're rebuilding claims intake, let's also redesign the workflow." That's a product decision masquerading as a migration task, and it extends timelines for no migration benefit. The new implementation must be feature-equivalent to the old one. New features go in the backlog, built after the domain is migrated, not during.

They underinvest in the facade. I've seen teams use a "temporary" NGINX configuration as their facade and spend the rest of the programme fighting its limitations. The facade is the most important infrastructure investment in the programme. Get it right before you start migrating.

They understaff the legacy system during migration. The legacy system doesn't stop breaking just because you're migrating away from it. You need enough capacity to keep it stable while also building the new system. Under-resourcing the legacy support during migration is a reliable way to generate incidents that halt the migration.

💡

The strangler velocity rule

As a rough heuristic: if your Strangler Fig programme is not reducing legacy system traffic by at least 8–10% per quarter, something is wrong — either with the facade, with domain decomposition, or with team prioritisation. Use this as an early warning signal, not a post-mortem finding.

The Business Case Is the Architecture Case

Boards and CEOs sometimes struggle with the Strangler Fig because it doesn't produce a "launch day." There's no moment where everything is new. There's a continuous gradient.

Frame it differently: the Strangler Fig produces business value throughout the programme, not only at the end. Every migrated domain is a domain where engineering velocity is higher, operational costs are lower, and the system is more maintainable. The ROI is visible at month 3, month 6, month 12 — not only at month 24.

At the reinsurer, we modelled the migration cost against the continued cost of operating and developing in the legacy system. The migration programme paid for itself within 14 months of completing the first major domain migration, and the full cost was recovered within 22 months of programme start. By month 30, the organisation was operating a system that cost 62% less to run and could accept new product requirements in days rather than sprints.

That is the argument for the Strangler Fig. Not architectural elegance. Not technical correctness. The compounding business return of a system that gets better every month, rather than one that requires a bet-the-farm launch to improve at all.


If you're facing a legacy modernization decision — whether that's a 10-year-old monolith, a core insurance system, or an enterprise platform that's becoming a constraint — let's talk. A 30-minute discovery call is enough to determine whether the Strangler Fig is the right pattern for your system and your timeline.

Ready to act

Ready to put this into practice?

I help companies implement the strategies discussed here. Book a free 30-minute discovery call.

Schedule a Free Call