73

Strangler Fig: strangle legacy route by route, don’t rewrite it

#
  • pattern
  • established
  • config

A big-bang rewrite violates Gall’s Law (41) on an industrial scale. Strangler fig: a facade in front of the legacy system, routes moved to the new system one at a time, the legacy dies by displacement. Every step is reversible (route back), progress is measurable (% of traffic), and the system keeps running the whole time.

The name is Martin Fowler’s, from his 2004 bliki entry “StranglerApplication” (later retitled “StranglerFigApplication”), after the fig vines he saw in Australian rainforest: they grow around a host tree until the tree dies and the fig stands on its own. The argument against the alternative is about risk and value: a rewrite delivers nothing until it reaches parity with a system whose behavior is only partly documented, while the old system keeps changing underneath it (76). Strangling delivers each migrated route as soon as it moves, and the parts nobody ever migrates turn out to be the parts nobody needed.

Code example (config)
Routingconfig
# routing IS the migration mechanism
routes:
  - match: { path: /invoices/* }   # migrated
    backend: billing-v2
  - match: { path: /* }            # everything else: legacy, for now
    backend: legacy-monolith

One route, done properly: put the facade in front first with no behavior change; then shadow /invoices/* — send each request to both, serve the legacy answer, and diff the two responses until the mismatch rate is near zero and every remaining difference is explained; then serve from the new system for a slice of tenants, then all; and only then delete the legacy code for that route. Each step has a metric and a rollback that is a routing change.

The most expensive part is not the routing but splitting the data: while both systems write to one database, the legacy isn’t dead, just hidden. A shared DB is a way station with a departure date; otherwise you’ve built a distributed monolith. Data moves by expand–migrate–contract (17) or change data capture (104), with one system owning writes at any time. Strangling also needs a seam: a batch job with no interface to intercept has to be cut at its inputs and outputs instead.

Last technical review: 2026-08-04 · Reference · 112 principles