PromptForge Academy
legacy-modernizationmigrationarchitectureexisting-projects

Legacy Modernization with AI: The Strangler Fig Pattern

Big-bang rewrites fail far more often than they succeed. The strangler fig pattern — incrementally routing traffic away from legacy code until it can be retired — is safer, and AI removes most of its planning overhead.

"Let's rewrite it properly" is the most expensive sentence in software engineering. Full rewrites take longer than estimated, the old system still needs maintenance while the new one is built, and by the time the rewrite ships, requirements have moved. The strangler fig pattern — named after the vine that grows around a host tree until the tree can be removed — replaces the all-or-nothing rewrite with incremental, continuously-shippable migration.

How it works

  1. Put a routing layer (a reverse proxy, an API gateway, or a facade) in front of the legacy system.
  2. Build one new module against the new architecture, functionally equivalent to a slice of the legacy system.
  3. Route traffic for that slice to the new module; everything else still goes to legacy.
  4. Verify in production with real traffic before routing the next slice.
  5. Repeat, module by module, until nothing is left routing to legacy — then retire it.
The property that makes this safe

At every point in the process, the system is fully functional and in production. There is no "big cutover night." A bad module can be rolled back by routing traffic back to legacy — a full rewrite has no equivalent rollback.

Where AI actually helps

The planning work — deciding what to extract first, in what order, and how risky each slice is — is normally the slowest part, because it requires understanding a legacy codebase nobody fully remembers writing. This is exactly the kind of large-context analysis AI is strong at, provided you give it the discipline of a structured prompt rather than "look at this codebase and tell me what to do."

Step 1 — migration readiness assessment

Before picking a first module, get an honest picture of what you're dealing with: coupling between modules, test coverage per area, and which parts are actually safe to touch. Feeding a codebase overview to Claude with an explicit rubric produces a more consistent assessment than an ad-hoc "what do you think" — and one you can defend to stakeholders.

Step 2 — module extraction plan

Prompt: rank extraction candidates by risk and value
Existing Project Advanced — Modernization module
Context: Legacy monolith, .NET Framework 4.8. Here is a module dependency map (which modules call which) and test coverage per module: [paste data].

Task: Rank the top 5 candidate modules for strangler-fig extraction, ordered by what to extract first.

Constraints:
- Score each candidate on: (a) how isolated it is from other modules (fewer inbound dependencies = safer first extraction), (b) test coverage (higher = safer), (c) business value of modernizing it soon.
- For each candidate, state the specific risk of extracting it first, not just the score.
- Do not recommend extracting the module with the most inbound dependencies first, regardless of its business value — that's a routing-layer/big-bang risk in disguise.

Output format: A table with columns: Module | Isolation score | Coverage | Business value | Recommended order | Key risk.

Step 3 — the routing layer

A reverse-proxy or API gateway (YARP is a common .NET choice) sits in front of both systems and routes by path, header, or feature flag. This is also where canary rollout and instant rollback live — route 5% of traffic to the new module, watch error rates, then ramp up or roll back.

Common failure modes of the pattern itself

Failure modeCauseFix
Extraction never finishesNo forcing function to retire legacy modules once replacedSet an explicit deadline per extracted module to remove the legacy code path, not just stop routing to it
Data drift between old and new systemsBoth systems write to separate data stores during transitionRoute writes through a single system (usually legacy) during transition, or use a synchronization/outbox pattern
"Strangler fig" in name only — actually a parallel rewriteNew system built in isolation, then swapped wholesaleEach extracted module must go live and serve real traffic before the next one starts — that's what makes it incremental
Routing layer becomes a second legacy systemRouting logic grows ad hoc without its own tests/ownershipTreat the routing layer as a first-class piece of infrastructure with its own test suite from day one

The pattern isn't free — it takes longer calendar time than a rewrite would take if the rewrite went perfectly. Its value is that it doesn't require the rewrite to go perfectly; each slice is independently low-risk, verifiable in production, and reversible. The Existing Project Advanced program covers the full assessment-to-extraction workflow, including how to combine this with the .NET Framework → .NET 8 migration path when that's the specific modernization target.