Insights · Modernization

Modernize without rebuilding

By Kale 6 min read

The first instinct when you inherit a legacy system is to rebuild it. The second instinct, after you scope the rebuild and realize what it costs, is to leave it alone forever.

Both are wrong. The right move is somewhere in the middle, and it has a name: the strangler fig pattern.

What the pattern is

The name is from Martin Fowler, but the idea is older. A strangler fig is a tree that grows around an existing tree, gradually replacing it from the outside in. The original tree dies. The fig stays. From a distance the silhouette looks the same.

Applied to software: you put the new system alongside the old one, route specific URLs or features to the new system as you build them, and decommission the old code piece by piece. At any given moment, both systems are live. Traffic shifts gradually. There’s never a “big bang” cutover.

What this looks like in practice

Suppose you have a 2014 PHP monolith. It’s slow, hard to maintain, and the engineer who wrote it left three years ago. You want to modernize, but a full rebuild would take a year and you can’t afford to freeze new features that long.

Strangler-fig approach:

  1. Stand up a modern app (whatever stack you’re moving to, say, Astro + a Node API) at a sibling URL or behind the same domain.
  2. Pick the smallest, most-isolated route in the old system. Often something like the marketing pages, or a “contact us” form. Rebuild that one route in the new app.
  3. Route traffic for that one route to the new app at the load balancer / reverse proxy / CDN level. The rest of the site still hits the old app. Users don’t notice.
  4. Validate. Watch metrics. Make sure conversions, page speed, and error rates didn’t get worse.
  5. Repeat with the next-smallest route. And the next. Slowly build out the new app’s coverage.
  6. Decommission the old code paths as their replacements ship and stabilize.

After 6-12 months of incremental migration, the old system handles essentially nothing. You delete it. The new system is now the system.

Why this works better than a rebuild

Lower risk. You can stop at any time. If the new stack turns out to be wrong for the job, you’ve only invested in a few routes, not a year-long parallel build.

Faster wins. The first migrated route is in production in weeks. You get to demo improvements (faster pages, cleaner UI, better SEO) immediately, instead of asking stakeholders to wait a year.

Funded by results. Each migrated route can usually justify its own build cost, better conversion, lower hosting cost, faster page loads. The rebuild pays for itself as it happens.

Real-world testing. You learn what’s hard about the new stack early, on small-blast-radius pieces, instead of discovering it during a big-bang launch.

When the pattern doesn’t fit

Two scenarios where strangler fig is the wrong choice:

  • The data model itself needs to change. If you’re moving from a single-tenant Postgres to a multi-tenant architecture, you probably can’t run both systems against the same database during the transition. You need a migration plan, not a strangler.
  • The system is genuinely small. If the legacy app is 5 routes and a database, just rebuild it in 3 weeks. Strangler fig is overhead that pays off only on systems too large to rebuild safely.

For everything else, and most legacy systems we see, it’s the right answer.

The honest summary: most modernization projects fail because they’re scoped as “replace the whole thing in one go.” Strangler fig is what shipping looks like instead.