Skip to content

Engineering insights

Decoupling a legacy monolith without a rewrite

A working playbook for the strangler pattern: where to cut first, how to keep the old system honest, and how to know you are done.

9 min read · For CTOs and engineering directors with a system nobody wants to touch

Why the big rewrite keeps failing

A full rewrite asks the business to freeze while engineering rebuilds years of behavior that was never written down. The old system keeps changing underneath you, the new one ships late, and for months you run two systems that both partly work.

The strangler pattern avoids that. You put a seam in front of the legacy system and move one capability at a time behind it. The business keeps running on the old system until each piece is proven on the new path.

Step 1: put a facade in front of everything

Before moving any logic, route traffic through a layer you own: an API gateway, a thin service, or a set of serverless functions. At first it does nothing but pass requests through and log them.

That log is the most valuable artifact of the whole project. It tells you which endpoints and workflows are actually used, which are dead, and where the volume is.

Step 2: choose the first slice by risk, not by size

A good first slice has clear inputs and outputs, a measurable result and limited blast radius if it goes wrong. Common good first candidates:

  • Read-only reporting that today requires an export and a spreadsheet
  • Notifications and messaging triggered by state changes
  • Intake from a new channel (a form, a partner webhook) that the old system was never built for
  • Payment and billing sync, where an external processor already holds the truth

Step 3: one adapter per legacy system

Every call into the old system goes through a single module. It handles authentication, retries, pagination, field mapping and every odd behavior you discover. When the vendor returns success with no ID, or the same page twice, that is fixed in one place.

This also gives you a clean place to write contract tests, so a vendor update that changes behavior fails a test instead of a customer workflow.

Step 4: decide who owns each piece of data

For each entity (customer, order, job, invoice), write down which system is the source of truth. Two systems that both claim to own a record will drift. Everything else should read from, or be derived from, the owner.

Step 5: make failure visible

Integrations fail quietly. Put every failed write in a dead-letter store with its payload and the reason, show it to the people who own the workflow, and let them retry it. Silent failure is the most expensive bug in any integration project.

How you know you are done

You are done with a slice when traffic for it no longer reaches the legacy code path, the monitoring proves it, and the old path can be switched off. You may never retire the legacy system entirely, and that is fine. The goal is that it stops being the bottleneck.

Next step

Tell us which system is slowing you down.

A 15 to 20 minute scoping call. If it is a fit, scope, price and timeline follow in writing.