Modernising without downtime is a sequencing problem, not a heroics problem
You modernise a legacy system without downtime by replacing it in small, reversible increments behind a stable boundary, never by switching everything over at once. The technique is old and well proven; what makes it work is discipline, not cleverness. The systems that go down during modernisation almost always do so because someone chose a big-bang cutover and hoped the testing was good enough.
For business-critical estates (core banking, billing, claims, provisioning, the order systems that keep a manufacturer shipping), “hope” is not a migration strategy. The good news is that there is a repeatable way to do this that keeps the lights on throughout.
The strangler-fig pattern
The strangler-fig pattern is the backbone of low-risk modernisation. The name comes from the fig that grows around a host tree, gradually taking over its structure until the original can be removed without the canopy ever falling.
Applied to software, it works like this:
- Put a boundary in front of the legacy system. A facade, gateway or proxy that all traffic flows through. Initially it does nothing but pass requests straight to the old system.
- Carve out one capability. Pick a single, well-understood slice of behaviour: one endpoint, one workflow, one report.
- Build the replacement behind the boundary. Implement that one capability in the new system.
- Redirect just that slice. The facade routes the chosen capability to the new implementation and leaves everything else untouched.
- Repeat. Capability by capability, the new system grows and the old one shrinks until there is nothing left to route to the legacy code.
The old and new systems run side by side for the entire journey. At no point is there a single irreversible switch. This is the spine of how we approach legacy modernisation in practice.
The hard part is usually not the routing. It is the seams. Shared databases, implicit state and undocumented side effects are what make a capability difficult to extract cleanly. Finding those seams is the real work, and it is why the assessment stage matters before any code is written.
Incremental delivery: small changes, frequently
The strangler-fig only stays safe if each increment is genuinely small. A “small” increment that takes four months to ship is a big-bang in disguise: the risk has simply been hidden behind a long timeline.
What small actually means:
- Each change touches one capability and can be deployed on its own.
- Each change is releasable in days or weeks, not quarters.
- Each change is observable in production before the next one starts.
Frequent, small releases compound a quiet advantage: every deployment exercises and proves the rollback path. Teams that deploy rarely discover, at the worst possible moment, that their rollback procedure was never real.
Parallel-run: proving correctness before you trust it
For the riskiest capabilities (anything involving money, regulated calculations or data that cannot be reconstructed), routing traffic is not enough. You need to know the new implementation is correct before it owns the result.
Parallel-run is the technique. You send the same input to both the legacy and the new implementation, return the legacy result to the user, and compare the two outputs in the background. Discrepancies are logged and investigated. Only once the new implementation has matched the old one across real production traffic for long enough to trust it do you promote it to the authoritative source.
Parallel-run is more expensive (you are running two implementations and a comparison harness), so it is reserved for the capabilities where being wrong is unacceptable. Used selectively, it turns “we think it works” into “we have evidence it works”, which is a very different conversation with a risk committee.
Rollback discipline is the safety net
Every increment needs an answer to one question, written down before it ships: how do we undo this in minutes?
That discipline shapes the technical choices:
- Decouple deploy from release. Ship the new code dark, then turn it on with a feature flag. Rolling back becomes flipping a flag, not redeploying under pressure.
- Keep changes backward-compatible. The new and old paths must coexist, so the facade can route either way at any moment.
- Handle data carefully. Schema changes are the hardest things to reverse. Expand-and-contract migrations (add the new shape, migrate, then remove the old shape in a later step) keep each individual change reversible.
- Rehearse rollback. A rollback plan that has never been executed is a hypothesis. Test it.
Where downtime sneaks back in
Even with the right patterns, a few things reliably cause outages:
- Data migrations under load. Migrating large tables in one transaction locks them. Batch the migration and run it online instead.
- Hidden coupling through shared state. If both systems write to the same store with different assumptions, you get corruption rather than a clean cutover. Untangle the data ownership before splitting the behaviour.
- The “while we’re in here” trap. Modernisation is not the moment to also add features or refactor unrelated code. Keep each increment to one purpose so that when something breaks, you know exactly what caused it.
Why the cutover stalls, and how to unstick it
There is a failure mode that no amount of clean engineering prevents, and it is worth naming because it is the one that quietly eats the most calendar. A manufacturing client of ours ran their old system and its replacement side by side for nineteen months. The new system worked. The build was finished. What nobody owned was the decision to switch the old one off, and what the rollback was if production broke at 2 a.m.
The usual advice, “name a date, assign an owner”, does not survive contact with the real blocker. The person who flips the switch is making a personal career bet under uncertainty, and no schedule removes that. So the parallel run becomes the safe choice for everyone, because keeping both systems alive has no single name attached to it and turning one off does. That asymmetry, not the engineering, is what stalls the cutover. Asking leadership to “sign off in writing” fixes neither half of it: executives will not sign a scary memo, and if the rollback plan cannot survive technical scrutiny, everyone in the room already knows it.
What actually moves it is changing the two things that create the asymmetry:
- Shrink the bet. Do not decommission the old system. Put it in warm standby behind a rollback you have rehearsed and timed: primary back on the legacy in under thirty minutes, tested twice before cutover. Now the decision is not “kill it forever,” it is “switch primary, with a proven way back.” A small reversible bet gets made; an unbounded one does not.
- Put a name on inaction, too. The dual runtime and the second on-call rotation go onto a monthly budget line with an owner. Keeping both systems alive stops being free and nameless and becomes a specific number a specific person has to defend each month.
Once the downside was bounded and the parallel run carried a price tag, that client’s cutover happened in two weeks, not because anyone got braver, but because we stopped asking anyone to be brave. The lever is not the signature. It is making the safe-looking option visibly expensive and the risky-looking option cheaply reversible.
The pattern underneath all of this
Modernising without downtime comes down to a single principle: never put yourself in a position where the only way forward is a leap. Keep a boundary in place, change one thing at a time, prove it in production, and keep every step reversible. It is slower to start and far faster to finish than the rewrite that stalls at 80 per cent.
If you are facing a core system that the business cannot afford to take offline, that is precisely the situation this approach is built for. Talk to TrueForge and we will map the seams, the sequence and the rollback path before anything moves.