The strangler-fig pattern: migrating a legacy system without freezing your roadmap

The pitch for a full rewrite is always the same: "the codebase is a mess, let's start clean." The cost is always the same too — a year (at minimum) where the roadmap is frozen, the old system still needs maintaining because the new one isn't ready, and the business is betting everything on one cutover date going well.
A strangler-fig migration routes traffic between old and new piece by piece, behind a routing layer, so the legacy system keeps running the whole time. Named for the strangler fig tree, which grows around a host tree and gradually replaces it — the metaphor is exact: nothing gets torn down until its replacement is already load-bearing.
Prioritisation matters more than sequencing. Start with whatever is actually costing the most right now — the module nobody wants to touch, the integration held together by a script someone wrote years ago and left — not a tidy top-to-bottom pass through the codebase. The parts that aren't causing pain can wait, and often should.
The routing layer is the part people underestimate. It needs feature flags per route or per customer, not a single global switch, so a bad migration can be rolled back for one account without affecting everyone else. That's what turns 'high-risk cutover' into 'reversible experiment.'
The end state looks the same as a rewrite — a modern system doing the job the legacy one used to. The difference is every step in between was shippable, reversible, and never once required freezing the rest of the product to get there.
Have a question about this article — or your own project?
Ask us anything about the approach above, or tell us what you're building. You'll hear back from an engineer, not a sales script.