Understand what it actually does

Legacy systems accumulate behaviour that exists for a reason nobody remembers: a special case for one customer, a retry because a partner is unreliable, a validation added after an incident.

Instrument the running system rather than relying on documentation. Log inputs, outputs, and the paths taken over a full business cycle, and you will have a specification that reflects reality rather than intention.

Find the seams

A seam is a place where behaviour can be intercepted without changing the surrounding code — an interface, a queue, a network boundary, a database view.

Where none exists, creating one is the first piece of work. It is unglamorous and it is what makes everything afterwards incremental rather than all-or-nothing.

Put a facade in front

Route all traffic through an interface that initially forwards everything to the existing system. Nothing changes functionally, and you now have a single point at which individual capabilities can be redirected.

This step alone is often resisted as overhead. It is the entire mechanism by which the migration stays reversible.

Move one capability at a time

Choose a capability that is well understood and not the most critical, implement it in the new system, and route a small share of traffic to it. Compare outputs against the old path before increasing the share.

  • Start with reads before writes — they are far easier to reverse
  • Run both paths in parallel and compare results before switching
  • Keep the old path available until the new one has run a full cycle
  • Move data ownership only after behaviour has been proven
  • Remove the old path deliberately, once, rather than leaving it indefinitely

Handle the data model last where possible

Data is the hardest thing to move incrementally, because two systems writing to two schemas creates reconciliation problems that compound.

Keep a single source of truth for as long as you can, even if that means the new system reads from the old database initially. Split the data only when the behaviour above it is settled.

Finish the job

The most expensive outcome is a half-finished migration where both systems run indefinitely, each with a share of the behaviour and nobody willing to remove either.

Put a date and an owner against decommissioning each part of the old system at the moment its replacement goes live, and treat that as part of the work rather than as cleanup.

Written by the Global IT Solutions engineering team. Working through this decision right now?

Start a conversation