Skip to main content
Xalicon
ModernizationDraft — in editorial review

The strangler pattern in practice: migrating without a cutover

How to move a business-critical system to new foundations one capability at a time, keeping rollback available at every step.

Written by
Xalicon Engineering · Modernization practice
Reviewed by
Xalicon Editorial · Technical review
Published
Updated
Reading time
8 minutes

Draft article

This article is written by the Xalicon team and is in editorial review. The reasoning reflects how we work today; the draft label means it has not yet had a final technical and editorial pass.

Why rewrites stall

A parallel rewrite has to reach feature parity before it delivers any value. Meanwhile the existing system keeps changing, because the business does not stop. The target moves, the estimate slips, and at some point the programme is quietly deprioritised.

The strangler pattern avoids this by delivering value continuously. Each migrated capability is live in production, and the programme can be paused at any point without leaving you worse off than when you started.

Start with the routing layer

Put a proxy in front of the existing system that can route individual paths to either the legacy application or a new service. This is the control point for everything that follows, and it should be in place before any migration work begins.

It also enables gradual traffic shifting. Moving 5% of traffic to a new implementation, comparing outputs, then increasing is dramatically safer than an all-at-once switch — and it makes rollback a configuration change rather than a deployment.

Characterisation tests come before code

Before replacing a capability, write tests that assert what the current system does — including behaviour that looks wrong. Those tests are your specification, and they frequently document rules that exist nowhere else.

Expect to find genuine bugs that users have adapted to. Do not fix them during migration. Record them, migrate the behaviour faithfully, and address them as a separate change afterwards so that any regression has one obvious cause.

Choosing the first slice

The first slice should be bounded, valuable and low-risk. It exists to prove the pattern, the tooling and the team’s confidence — not to tackle the hardest problem.

A read-heavy capability with clear inputs and outputs is ideal. Avoid anything that writes to shared state or sits on the critical revenue path until the pattern is established.

  • Bounded: clear inputs and outputs, limited shared state
  • Valuable: users notice the improvement
  • Frequently exercised: enough traffic to reveal problems quickly
  • Reversible: rollback has no data consequences

The data problem

Application logic is usually the easy part. Data is where migrations get stuck, because legacy schemas typically have consumers nobody has catalogued — reporting jobs, partner integrations, scripts on someone’s machine.

Change data capture keeps both stores consistent during transition, letting each consumer migrate independently instead of requiring one coordinated switch. Reconciliation reports prove the two sides agree before anything is decommissioned.

Knowing when to stop

Not everything needs migrating. Some capabilities are stable, rarely changed and perfectly adequate. Wrapping them behind a clean interface and leaving them alone is a legitimate outcome.

Others should simply be retired. Usage analysis frequently shows a significant share of a legacy surface has not been touched in a year. Deleting it is cheaper than migrating it, and it is the fastest progress you will make on the whole programme.

  • Legacy
  • Migration
  • Architecture

Related services

Consultation

Talk this through with an engineer

If this article describes a problem you are facing, a thirty-minute conversation will get you further than another article.

Prefer email? contact@xalicon.co