
Legacy software modernisation: options, risks and how to plan it
En bref
A practical guide to legacy software modernisation: how to tell when a system needs it, the options from rehosting to rebuilding, why incremental replacement usually beats a big-bang rewrite, and how to plan data, testing and the business case.
13 min de lecture
Legacy software modernisation means changing an old but still important system so it becomes safe, affordable and quick to change again, by moving, refactoring, replacing or gradually rebuilding it. The right approach depends on what is actually wrong: unsupported technology, a codebase nobody dares touch, missing skills, or a system that no longer fits the business. In most cases, replacing the system piece by piece while it keeps running is lower risk than a single big rewrite.
The problem is widespread and expensive. The US Government Accountability Office reported in GAO-25-107795 that federal agencies spend over $100 billion a year on IT and have typically reported spending about 80% of it on operating and maintaining existing systems. Of the 11 systems GAO identified as most in need of modernisation, eight relied on legacy programming languages, four ran on unsupported hardware or software and seven had known cybersecurity vulnerabilities. Private companies rarely publish numbers like these, but the pattern is familiar: a growing share of the budget goes to keeping old systems alive, leaving less for anything new.
What makes software legacy
Age alone does not make a system legacy. Plenty of decades-old software runs reliably and changes rarely, and that is fine. A system becomes a problem when the business needs it to change and it cannot change safely, quickly or affordably. The common symptoms fall into four groups.
- Technology risk: the language, framework, database, operating system or hardware is out of support, so security fixes no longer arrive. The US cybersecurity agency CISA lists use of unsupported or end-of-life software as a bad practice that significantly elevates risk, especially for internet-facing technology.
- Knowledge risk: the people who understood the system have left, documentation is missing, and the code holds business rules nobody can explain.
- Change risk: every change takes weeks, breaks something unrelated, and needs a manual release on a weekend. There are few or no automated tests.
- Fit risk: the system cannot support what the business now needs, such as a mobile app, an API for partners, new products, other countries or modern reporting.
Signs it is time to modernise, and when to leave it alone
- Security patches are no longer available for a component you rely on, or an auditor has flagged it.
- One or two people are the only ones who can change or operate the system, and losing them would be a crisis.
- Simple business changes, such as a new price rule or a new field, take weeks and carry real risk.
- Hosting, licences or specialist support cost more each year, and vendors are ending support.
- The system blocks strategic plans: new channels, integrations, acquisitions, or regulatory changes.
- Workarounds have grown around it: spreadsheets, manual re-entry, unofficial tools.
Equally, there are good reasons to leave a system as it is. If it is stable, secure, rarely needs to change and its supporting technology has a credible support path, modernising it may simply move risk and money from one column to another. In those cases it is often better to isolate it behind a clean interface, document it, make sure more than one person can operate it, and spend the effort elsewhere. Modernisation should be driven by a business outcome, not by the age of the code.
The modernisation options, from lightest to heaviest
Cloud providers popularised a vocabulary for these choices, often called the 7 Rs. AWS's version lists retire, retain, rehost, relocate, repurchase, replatform and refactor or re-architect, and it notes that refactoring is the most complex and costly route. The same ideas apply whether or not the cloud is involved. The table adapts them to modernisation in general.
| Option | What changes | When it fits | Main risk |
|---|---|---|---|
| Retire | The system is switched off; data is archived | Little use left, or its features exist elsewhere | Hidden users or reports nobody listed |
| Retain and encapsulate | Nothing inside; a clean API is put in front of it | Stable core that rarely changes but must connect to new things | Postpones the underlying problem |
| Rehost | Moves to new infrastructure unchanged | Data centre exit or hardware end of life | Same software problems, new hosting bill |
| Replatform | Moves with limited changes: managed database, containers, newer runtime | Runtime or platform out of support, code mostly sound | Scope creep into a larger rewrite |
| Refactor | Internal structure improved without changing behaviour | Code is worth keeping but hard to change | Slow if there are no tests to start from |
| Re-architect | Parts are rebuilt with a new design, often gradually | The design itself blocks the business | Long transition with two systems to run |
| Replace | A SaaS or packaged product takes over | The process is standard and not a differentiator | Business must adapt to the product; data migration |
| Rebuild | New software is written to replace the old | Unique processes, old system cannot be evolved | Underestimating hidden behaviour; long time before value |
Most real programmes combine several options. A typical portfolio retires a few systems, replaces commodity ones such as HR or accounting with SaaS, replatforms some, and reserves deeper re-architecture for the one or two systems that hold the business's distinctive logic. Our guide to cloud migration services covers the infrastructure side in more depth.
Rewrite or replace gradually? The most important decision
The tempting plan is to freeze the old system, build a shiny new one in parallel and switch over on a single date. It rarely goes well. In his essay Things You Should Never Do, Joel Spolsky describes how Netscape's decision to rewrite its browser left it without a new major release for close to three years, and argues that old, ugly code often contains years of fixes for real-world problems that a rewrite throws away. Martin Fowler makes a related case in his description of the strangler fig application: like-for-like rewrites take long, users cannot wait that long for new features, and existing behaviour is hard to specify, much of it no longer wanted.
Big-bang rewrite
Build a complete replacement, then switch everyone over on one date. It can work for small systems with well-understood behaviour and a short build. For anything larger, it delays all value until the end, lets requirements drift for months or years, and concentrates risk into a single cutover where any missed behaviour hits every user at once.
Big-bang rewrite
Build a complete replacement, then switch everyone over on one date. It can work for small systems with well-understood behaviour and a short build. For anything larger, it delays all value until the end, lets requirements drift for months or years, and concentrates risk into a single cutover where any missed behaviour hits every user at once.
Strangler fig (incremental)
Put a routing layer in front of the old system, then build new parts one by one and divert traffic to them. The legacy system shrinks until it can be switched off. Value arrives early, each step is small and reversible, and the team learns about the old system as it goes. The cost is transitional architecture: temporary code to keep old and new in step, which must eventually be removed.
Refactor in place
Keep the system and improve it from the inside: add tests, upgrade the runtime, untangle modules, extract services where it helps. It suits code that is fundamentally sound but neglected. It is the least disruptive option, but it needs discipline, because refactoring that is never scheduled never happens.
Replace with a product
Adopt a SaaS or packaged product and migrate data and users to it. It is often the best answer for processes that are standard across companies, such as payroll, accounting, ticketing or document management. Success depends on changing the process to fit the product rather than customising the product until it becomes a new legacy system.
The goal of modernisation is not new code. It is a system the business can change safely again, and the fastest way there is usually a series of small, reversible steps that each deliver something.
Start with an assessment, not a technology choice
Before choosing tools or architecture, understand what you have and what the business needs from it. A focused software audit of a few weeks usually pays for itself by preventing the wrong plan. It should cover:
- Business outcomes: what must improve and how you will know. Faster changes, lower run costs, a security finding closed, a new channel enabled, a vendor exit by a fixed date.
- Capabilities and users: what the system actually does, who uses which parts, and how often. Usage data often shows large parts are barely touched.
- Code and dependencies: languages, frameworks and libraries, their support status, known vulnerabilities, test coverage and the areas that change most often.
- Data: the schemas, data quality, volumes, retention rules and the data other systems read directly.
- Integrations: every inbound and outbound connection, including file transfers, scheduled jobs and reports that read the database.
- Operations: how it is deployed, monitored, backed up and recovered, and who knows how.
- Hidden behaviour: business rules buried in stored procedures, triggers, batch jobs and configuration.
- People and contracts: who understands the system, licence and support end dates, and notice periods.
Fowler and colleagues' patterns of legacy displacement frame the work as four activities: understand the outcomes you want, break the problem into smaller parts, deliver those parts successfully, and change the organisation so the new system does not decay into the next legacy. That last step is the one most plans forget.
Techniques that take the risk out of modernisation
Characterisation tests
Before changing legacy code, capture what it does today, right or wrong, in automated tests. Feed it real inputs and record the outputs. These tests do not judge whether the behaviour is correct; they tell you when you have changed it. They turn a terrifying change into a measurable one.
Seams and an anti-corruption layer
Find or create seams: places where you can split the system, such as a module boundary, an API, a message queue or a database table that one area owns. Put a translation layer between new and old components so the new design is not polluted by the old data model. This anti-corruption layer is also where you handle the awkward mappings, odd codes and special cases the old system relies on.
Routing, interception and parallel runs
- Route by capability: a gateway or proxy sends requests for migrated features to the new system and everything else to the old one.
- Event interception: capture changes in the old system and publish them as events the new components can use, so both stay in step during the transition.
- Dark launching and parallel runs: send the same inputs to old and new code, compare the outputs, and fix differences before any user sees the new results.
- Canary releases and feature flags: move a small group of users first, watch the results, and roll back with a switch rather than a redeploy.
- Build as you mean to continue: automated tests, deployment pipelines and monitoring from the first new component, not added at the end.
Data migration: usually the hardest part
Code can be rewritten; years of business data has to be carried across intact. Legacy databases often hold duplicates, overloaded fields that mean different things in different decades, codes whose meaning lives only in someone's head, and integrity rules enforced by the application rather than the database. Treat data migration as a workstream of its own, started early.
- Profile the data: volumes, nulls, duplicates, invalid values and how fields are really used.
- Agree the target model and the mapping for every field, including what happens to records that do not fit.
- Decide what to clean before migration, what to clean after, and what to archive rather than move.
- Automate the migration so it can be run repeatedly, and rehearse it on full copies of production data.
- Reconcile after each run: record counts, totals and spot checks agreed with the business owners.
- Choose a cutover approach: a one-off move during a freeze window, or continuous sync while old and new run side by side.
- Keep the old data read-only and accessible for an agreed period, for audits and for the questions nobody predicted.
During an incremental migration, old and new systems often need to share data for months. That makes system integration part of the modernisation plan: decide which system owns each entity at each stage, and make the synchronisation idempotent and monitored.
Where AI helps in modernisation, and where it does not
AI coding tools have changed the economics of some modernisation tasks. They are useful for reading unfamiliar code and summarising what a module does, drafting characterisation tests, explaining old languages and frameworks to engineers who never used them, translating routine code between languages, and generating documentation from source. Used well, they shorten the discovery phase and the repetitive parts of a migration.
They do not remove the need for judgement. A model can describe what code does but not why the business needed it, whether a strange rule is a bug or a regulatory requirement, or which behaviour users actually depend on. Automated translation of a whole codebase tends to reproduce the old design in a new language, carrying the old problems along. And generated code still needs to be reviewed, tested and owned by engineers who understand it. Treat AI as an accelerator for skilled people, not a replacement for the assessment and testing described above.
Building the business case without inventing numbers
Modernisation competes for budget with new features, so it needs a business case. Keep it honest and grounded in your own data rather than industry averages that may not apply to you.
- Cost to run today: hosting, licences, specialist support contracts and the engineering hours spent on keeping the lights on, taken from your own records.
- Cost of change: how long typical changes take now, how many releases fail, and what that delays. Delivery metrics from your tracker and deployment history are good evidence.
- Risk: support end dates, open security findings, single points of knowledge, and what an outage or breach of this system would cost.
- Opportunity: the specific initiatives blocked by the system, and what they are worth if unblocked.
- Cost of the programme: effort, the temporary cost of running old and new in parallel, and the disruption to teams.
Effort is driven by the size and tangle of the codebase, how much hidden behaviour it holds, data volume and quality, the number of integrations, compliance requirements, and how much the business can tolerate disruption. As an illustration of shape rather than a quote: an assessment and plan for a mid-sized line-of-business system is often two or three weeks for one or two senior engineers. Moving a single module out of a monolith behind a routing layer, with tests, data sync and a monitored cutover, might take a small team six to twelve weeks. Full programmes are better planned as a sequence of such slices than as one large estimate. Our software cost calculator can help frame the conversation.
Why modernisation projects fail
- Aiming for feature parity. Rebuilding everything the old system does, including features nobody uses, makes the project huge and delays all value to the end.
- No clear outcome. Without a measurable goal, scope drifts and the programme loses sponsorship halfway.
- Underestimating data. Migration is left to the end and turns out to be the hardest part.
- Freezing the business. Stopping all changes to the old system for a long rewrite frustrates users and pushes them to workarounds.
- Never finishing. The new system goes live but the old one is never switched off, so the organisation pays for both indefinitely.
- Rebuilding the same problems. The same team structure, practices and missing tests produce a new legacy system within a few years.
- Losing the experts. The people who understand the old system are not involved, or leave before their knowledge is captured.
After modernisation: keeping it from becoming legacy again
Software becomes legacy through neglect, not just time. Budget for regular dependency and runtime upgrades, keep automated tests and deployment pipelines healthy, track delivery metrics such as lead time and change failure rate, and keep documentation next to the code. Decide who owns the system and its roadmap. Our guide to software maintenance and support covers what that ongoing work involves.
How Authect approaches legacy modernisation
Authect is a founder-led software studio: you talk to the founders who assess and rebuild your system, never a salesperson, and every project is led by a senior engineer. We start with an assessment of the code, data, integrations and the outcomes you need, and we will tell you plainly if retaining, replacing with a product or simply documenting the system is the better choice. When we modernise, we favour incremental replacement with characterisation tests and parallel runs, and we use AI-accelerated delivery to speed up discovery and repetitive migration work, with an engineer reviewing every line.
You own the code, infrastructure and documentation from day one, with no lock-in. Work can be scoped as a fixed-price assessment or slice, run as monthly sprints across a longer programme, or continue under support and evolution once the new system is live. Read more about our legacy modernisation work, or talk to the founders about the system that is holding you back.
FAQ
What is the difference between legacy modernisation and migration?
Migration moves a system to a new place, such as from a data centre to the cloud, often with few or no code changes. Modernisation changes the system itself so it becomes easier and safer to change: refactoring, re-architecting, replacing or rebuilding parts of it. Many programmes do both, often migrating first and modernising afterwards, or modernising piece by piece as part of the move.
Should we rewrite our legacy system from scratch?
Usually not in one go. Big-bang rewrites delay all value until the end, tend to miss hidden behaviour, and concentrate risk in a single cutover. Incremental replacement, where new components gradually take over from the old system, is lower risk for most systems. A full rewrite can make sense for small systems with well-understood behaviour, or where the old platform truly cannot be run alongside new components.
What is the strangler fig pattern?
It is an approach to replacing a legacy system gradually. A routing layer sits in front of the old system, new functionality is built in a new system, and traffic for each capability is diverted to the new code as it becomes ready. Over time the old system shrinks until it can be switched off. The name, popularised by Martin Fowler, comes from a vine that grows around a host tree and eventually replaces it.
How long does legacy modernisation take?
An assessment and plan usually takes a few weeks. Individual slices of incremental modernisation, such as moving one module or capability, often take a small team a couple of months. Full programmes for large systems can run for a year or more, but they should deliver usable improvements every few weeks or months rather than only at the end.
Can AI convert our old code to a modern language automatically?
AI tools can translate routine code, explain unfamiliar languages, draft tests and documentation, and speed up discovery considerably. They cannot tell you which behaviour the business still needs or why a rule exists, and line-by-line translation tends to carry the old design and its problems into the new language. Use them to accelerate experienced engineers, with every change reviewed and tested.
How do we keep the business running during modernisation?
Modernise in small slices, keep the old system running for everything not yet migrated, synchronise data between old and new during the transition, and use parallel runs, canary releases and feature flags so each switch can be reversed quickly. Plan cutovers for quiet periods and agree rollback criteria in advance.
When should we replace a legacy system with SaaS instead of rebuilding it?
When the process it supports is standard across companies and does not set you apart, such as accounting, payroll, HR or ticketing. A good SaaS product will be cheaper to run and keep improving without your effort. Rebuild only where the system holds processes, rules or data that are genuinely specific to how your business competes.

