THIS EXPLANATION
THE ROOM
CDA·185 Computing, Data & AI 7 MIN · 8 STATIONS

Replacing a system you cannot turn off

A Socratic walk-through of replacing a system you cannot turn off — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

How do you rebuild something while it continues to run every day without interruption?

The natural plan is to build the replacement, test it thoroughly, and switch over one weekend. It is how we replace almost everything else — a boiler, a car, a payroll provider. Yet applied to a system that has been running a business for fifteen years, this plan fails so reliably that the industry gave the failure its own name.

Which is strange, because nothing about it is obviously wrong. So the interesting question is not "what should we do instead" but "what is different here that makes the obvious plan fail?"

b

Reasoning it through

REASONING #

Two things are different, and they compound.

The first is that you cannot stop. Orders keep arriving, payroll runs on the 25th, the regulator's file goes out monthly. That means the replacement is not a project with a delivery date; it is a project that must arrive without a gap, which rules out any plan whose risk is concentrated in a single moment.

The second is worse and less often said aloud: you do not know what the old system does. Not fully. The documentation describes intentions from years ago; the code contains behaviour nobody chose, added under pressure, relied on ever since. Some of those behaviours are bugs that downstream systems have adapted to. The old system is not an implementation of a specification — it is the specification, and it is written in a language you can only read by running it.

Put those together and see what a big-bang rewrite demands. Reproduce every behaviour, including the ones nobody has discovered, before any of it can be validated against reality — and do it while the target keeps moving, because the old system will not go into a feature freeze for three years. The gap between the two grows for as long as the project runs. The failure mode is not that engineers write bad code; it is that the plan requires knowledge which only exists on the other side of the cutover.

So invert the constraint. If risk cannot be concentrated at a moment, spread it: replace one capability at a time, each small enough to verify in production and to reverse quickly if it misbehaves. This is Martin Fowler's strangler fig pattern — he wrote it up in 2004, originally as the strangler application — and the botanical image is apt because the new growth surrounds the old before anything is removed.

Notice what that requires before any code is written: a seam. Something must sit between the callers and the old system and be able to route a given request either way — an HTTP facade, an API gateway, a message interceptor. Without such a point, there is nowhere to make an increment small. Building and proving that seam, while it still routes everything to the old system, is the real first milestone, and it is the one most often skipped in favour of starting on the interesting part.

Which slice goes first? The instinct is the easiest one. The better criterion is a capability with a clean boundary, real traffic, and a checkable output — because the first slice exists to prove the routing, the rollback and the observability on something you can afford to get wrong.

And now the part that decides whether the approach works: data. Code splits neatly; a database does not. If both systems read and write the same records, nothing has been decoupled. The rule that keeps this tractable is that exactly one system owns each piece of data at a time and everything else reads a replica — typically kept current by change data capture, flowing in the direction ownership dictates. Dual writes, where both systems write the same truth independently, look like the obvious bridge and are the most reliable way to end up with two versions of reality; if you must, treat reconciliation as a permanent job rather than a safeguard.

Finally, the characteristic failure here is not a disaster but a stall. Half the slices move, the urgent ones are done, attention drifts — and now you run two systems, two rotas, and a facade nobody fully understands, with only the hard slices left. That state persists for years. It is avoided by treating decommissioning as the deliverable, with a date, rather than as a consequence of finishing.

c

The analogy

THE ANALOGY #
THE FIGURE

Think of replacing a bridge that carries traffic every day. You do not close it and build a new one; you erect the new spans alongside, move one lane across, watch it under real load, then move the next. Traffic never stops, and at every moment there is a lane you can move back onto.

WHERE IT BREAKS DOWN

Bridge lanes are physically independent, whereas a moved software capability usually still reads and writes the same database as the old system — so the lane you moved is still resting on the old deck, and that shared foundation, not the traffic, is what makes the migration hard.

d

Clarifying the model

THE MODEL #

Three refinements.

First, incremental does not mean slow. Each slice is fast; the whole is long. What incrementalism buys is that value arrives continuously and every increment is reversible, so the cost of being wrong is one slice rather than one programme. Big-bang plans are often shorter on paper and far longer in practice, because their remaining time is unknowable until the end.

Second, "replace like for like" is a trap in one direction and a discipline in the other. Behaviour callers depend on must be reproduced, including the ugly parts, or you have not migrated — you have changed the product mid-flight and merged two risks. But reproducing the old internals imports the constraints you were escaping. Hold the line at the interface: same observable behaviour, freely different implementation.

Third, a misconception: that the facade is temporary scaffolding. It usually is not. Once callers point at it, it becomes the system's public interface, and it deserves the design attention of a permanent component rather than the care given to something you expect to discard.

e

A picture of it

THE PICTURE #
Replacing a system you cannot turn off
Replacing a system you cannot turn off Read left to right as elapsed time, and notice where the risk sits. The second period delivers no user-visible benefit at all -- everything still runs on the old system -- yet the whole approach depends on it, because it creates the place where an increment can be made small. The fifth period is a warning rather than a milestone: it is where migrations stall, having taken the easy slices. Only the last period is finished, and it is defined by nothing calling the old system rather than by the new one being complete. {"generator":"[email protected]","source":"../Socrates/.diagram-cache/_src/replacing-a-system-you-cannot-turn-off.md","sourceIndex":1,"sourceLine":4,"sourceHash":"f28157d89e22886390c41020c082ff22153e6b330ae6fa6a44a9b9068a44150d","diagramType":"timeline","layoutVariant":"source","repairedDuplicateIds":[],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":1554,"height":507},"qa":{"passed":true,"findings":[]}} All traffic to the oldsystem Behaviour isundocumented butobservable Insert the seam A facade takesevery call and stillroutes it to the oldsystem Move the first slice One capability witha clean boundaryand real traffic Move dataownership One owner perrecord and areplica flowing theother way Shrink theremainder The hard slices arewhat is left andneed explicitfunding Decommission Nothing calls theold system and it isswitched off

How to readRead left to right as elapsed time, and notice where the risk sits. The second period delivers no user-visible benefit at all — everything still runs on the old system — yet the whole approach depends on it, because it creates the place where an increment can be made small. The fifth period is a warning rather than a milestone: it is where migrations stall, having taken the easy slices. Only the last period is finished, and it is defined by nothing calling the old system rather than by the new one being complete.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

The obvious plan fails because it needs, before cutover, knowledge that only exists after it. Replacing a live system is therefore a search rather than a build: install a seam you can route through, move one capability at a time under real traffic, give every record exactly one owner, and keep each step reversible — and treat turning the old thing off as the deliverable, because a migration that stalls half-done costs more than either system alone.

g

Where to go next

ONWARD #
  • Branch by abstraction, the in-process cousin of the seam, for replacements inside one codebase.
  • Change data capture, and how it keeps a replica current without dual writes.
  • Running old and new side by side on the same traffic to prove equivalence before switching.
h

Key terms

TERMS #
TermWhat it means
Strangler fig patternreplacing a system by routing capabilities to a new one behind a facade until the old one carries nothing.
Seaman interception point where a call can be routed to either implementation.
Data ownershipthe rule that exactly one system is authoritative for a given record at a time.
Change data capture (CDC)streaming a database's committed changes so another store stays current.
Dual writetwo systems independently writing the same truth; a common source of silent divergence.
Branch by abstractionan abstraction layer inside a codebase that lets an implementation be swapped incrementally.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4