A logistics company's core booking system was built in 2007. The original developer retired in 2019. There's one person left who understands the codebase. It runs on a server in the server room that nobody is allowed to move because the last time they tried to restart it, it took six hours to come back up. Every new feature request that touches that system takes three times as long as expected, because nobody fully understands how it works.
This is not a technical curiosity. This is a strategic liability. The system is the single point of failure for the entire business — and every month of inaction increases the cost and risk of eventually having to deal with it.
The True Cost of Legacy Systems
Organisations systematically underestimate the cost of legacy systems because most of the cost is invisible. The IT budget line shows maintenance costs. It doesn't show:
- Engineer time consumed supporting the legacy system instead of building new capability
- Feature velocity lost because the system is too fragile to modify quickly
- Integration costs for every new system that needs to connect to the legacy core
- Security exposure from an unmaintained codebase with known vulnerabilities
- Business opportunities not pursued because the system can't support them
- The eventual forced-migration risk — when the system fails in production and has to be replaced under crisis conditions rather than on a planned timeline
The Three Modernisation Strategies
Strangler Fig
Build new functionality alongside the legacy system, routing traffic for specific features to the new system while the legacy handles everything else. Over time, the new system handles more and more, until the legacy is "strangled" — still running but doing nothing critical. Then decommission it. This is the lowest-risk approach for large, complex systems because it's fully reversible at every step.
Modular extraction
Identify the highest-value module within the monolith — often the module that changes most frequently or causes the most pain — and extract it as a standalone service. The monolith still exists, but it's smaller and the extracted module can evolve independently. Repeat until the monolith is a manageable size or fully replaced.
Parallel build
For systems that are sufficiently small and well-understood, build the replacement from scratch while the old system runs in parallel, then cut over. Higher risk, but faster if the scope is genuinely bounded.
The Rule We Never Break
Never modernise without understanding why the legacy system works the way it does. Every "why on earth does it do this?" in legacy code has an answer — sometimes it's technical debt, but often it's a business rule that was learned the hard way and never documented. Rewriting without understanding means reimplementing bugs that are actually features. The discovery phase of any modernisation engagement is not optional — it's where you find the things that will make your new system work.
Ready to solve this for your business?
Talk to our engineering team about your specific challenge.