All guides0 of 7 answered
Legacy Modernization: Bringing an Older System Up to Date

If it ain't broke, don't rewrite it.

Is your software in decent shape, and you want AI tools to work well in it? See AI-Ready Software →

Most companies run on software that is older than they would like. It works, the business depends on it, and every change has become slow and risky. The tempting answer is to start over, now often with the hope that AI will do the rewrite. The people who shaped this field advise the opposite: keep what works and replace the rest piece by piece, with a safety net. This guide goes through that method step by step, and shows where AI helps and where it does not.

  • About 12 minutes
  • Written for owners, useful for technical leads
  • Questions along the way are optional
  • Useful even if you never hire us

Updated

Background

Why old systems get hard to change

Software rarely breaks all at once. It gets harder to change, one shortcut at a time.

Ward Cunningham, who coined the term “technical debt” in 1992, compared quick, not-quite-right code to borrowing money. The debt is fine if it is paid back soon. If not, it keeps costing: (Cunningham, 1992)

Every minute spent on not-quite-right code counts as interest on that debt. (Cunningham, 1992)

The cost can be measured. A study of 39 production codebases found that low-quality code had 15 times more defects than high-quality code, and fixing issues in it took on average 124% more development time. (Tornhill and Borg, 2022)

The other half of the problem is knowledge. Michael Feathers, who wrote the standard book on the subject, defines legacy code simply as “code without tests”. Without tests, nobody can tell whether a change broke something. Often the people who knew why the system works the way it does have left. (Feathers, 2024)

ExampleA 60-person wholesale distributor runs ordering and stock on a system built in-house 15 years ago. Two developers still know it. A change to the delivery rules takes six weeks, because nobody is sure what else depends on them.

If one or two people are the only ones who understand the system, that is the first risk to fix, before any technology.

Background

Why the big rewrite usually fails

The obvious answer is to start over. It is usually the wrong one.

In 2000, Joel Spolsky called rewriting working software from scratch the single worst strategic mistake a software company can make. His reason: (Spolsky, 2000)

Old code has been used. It has been tested. Lots of bugs have been found, and they've been fixed. (Spolsky, 2000)

Throw the code away, and you throw that knowledge away with it. Martin Fowler reports the same from practice: replacing a system in one go sounds simple, but “we've seen this simple-sounding plan go down in flames most of the time”. A rewrite takes years, the business can't wait that long for changes, and much of the old behaviour turns out to be needed after all. (Fowler, 2024)

His alternative is a gradual modernization called the strangler fig, after a plant that grows around a tree until it can stand on its own. The new system grows around the old one, piece by piece, until the old one can be switched off. The steps in this guide follow that method. (Fowler, 2024)

A rewrite is sometimes the right call: a small system, a dead platform, and rules that are simple to state. Even then, move it in pieces. Moving to a ready-made product is a modernization too; the same steps apply to the data and the rules you take along.

Background

What AI changes, and what it doesn't

AI helps most with understanding old code and with mechanical, well-tested changes. It does not replace knowing what the system must do.

Many companies look at their old system again because they expect AI to do the work they put off for years. Google's DORA research, based on nearly 5,000 technology professionals, found: (DORA, 2025)

AI's primary role in software development is that of an amplifier. It magnifies the strengths of high-performing organizations and the dysfunctions of struggling ones. (DORA, 2025)

A year earlier, DORA estimated that more AI use went with slightly worse delivery: 1.5% less throughput and 7.2% less stability for every 25% increase in AI adoption. Their explanation is that teams may have forgotten the importance of small batches of change. (DORA, 2024)

AI is strongest at understanding old code. Thoughtworks now treats using it to understand legacy codebases as “a practical default rather than an experiment”. Their consultants see as much value in understanding existing code as in writing new code, and say tools that promise to replace the developers end to end are still a long way from the quality needed. Code that AI converts to a new language still needs lengthy testing, which is harder where there was no safety net to begin with. (Thoughtworks Radar, 2025) (Ferri et al., 2024)

AI is useful for mechanical changes, with tests and review around it. In one large migration at Google, 80% of the code changes were written entirely by AI, and engineers estimated the total time was cut by about half. But in most cases a reviewer had to undo some of the AI's changes, and in another migration the bottleneck was how fast engineers could review. That was a team with strong tests and review, on a well-defined change. (Nikolov et al., 2025)

AI can accelerate analysis, but it cannot replace domain understanding. (Palanisamy and Thiagarajan, 2025)

Feathers uses AI to explain code and to write tests that record what the system does now. He also warns that it makes code easier to write than to understand, and advises smaller steps and starting where mistakes are cheap. (Feathers, 2024)

So the classic methods matter more with AI, not less. Tests, small steps and replacing piece by piece are what make AI-written changes safe to accept.

Step 1

Agree what “up to date” must achieve

Start with the business outcome, not the technology.

Fowler's first activity for any modernization is to understand the outcomes you want to achieve. Faster changes to pricing rules, a supported platform, lower running costs, less dependence on two people: each points to a different first piece. (Fowler, 2024)

  • Write down the two or three outcomes that matter most.
  • For each, name the part of the system it touches.
  • Decide how you will know it worked, for example: a change to the delivery rules takes days instead of weeks.

These questions are optional. Your answers shape the personal plan at the end and stay in this browser.

Why bring it up to date now?

Choose all that apply.

Add a comment (optional)

What is the plan so far?

Add a comment (optional)
Step 2

Find out what the system really does

Before changing anything, recover what the system does and why.

This is where AI helps most today. Use it to explain code, draw the flows and answer questions about business rules. Then check what it says. Thoughtworks advises confirming every finding in at least two independent places, noting where each one came from, and having an expert confirm it, especially for business-critical rules. (Palanisamy and Thiagarajan, 2025)

  • List the main business rules the system carries.
  • Have the people who know the system review what AI or the team wrote down.
  • Keep the result next to the code, where the next developer and the next AI tool will find it.

Who knows how the system works?

Add a comment (optional)

Do you have the source code?

Add a comment (optional)
Step 3

Pin down today's behaviour with tests

Before you change the system, record what it does now.

Feathers calls these characterization tests: tests “that you use to describe the current behavior of the system”. They don't say what the system should do. They record what it does today, so any change that alters it shows up. (Feathers, 2024)

AI weakens the old excuse that there is no time to write tests: it can draft them in hours. It does not make checking them optional. A person confirms each test checks something real.

  • Start with the flows the business can't afford to break: placing an order, invoicing, payroll.
  • Record real inputs and the outputs the system gives today.
  • Run the tests on every change.

Are there automated tests the team trusts?

Add a comment (optional)
Step 4

Cut the system into pieces you can replace

A system is replaced in pieces, so find where it can be cut.

Feathers calls such a place a seam: “a natural breaking point where you can actually go and replace one thing with another”. Fowler's second activity is to decide how to break the problem up into smaller parts. (Feathers, 2024) (Fowler, 2024)

Start with the part that changes most often and hurts most, not with the oldest part. Avoid starting with the most tangled core. If unsupported technology is the reason to modernize, the unsupported parts come first; among them, start with the one that changes most often.

  • Map the main parts and what each one depends on.
  • Pick the first piece where the outcome from Step 1 is largest and the risk is manageable.
Step 5

Replace piece by piece, old and new side by side

The new part takes over one piece at a time, while the old system keeps running.

Fowler accepts temporary code to make this work: a transitional architecture that lets the new and the old system run side by side, removed once the move is done. (Fowler, 2024)

Inside the code, the same idea is called branch by abstraction: a way to make a large change gradually while the system keeps being released. Sam Newman describes both patterns as ways to move functionality from an old system to a new one step by step. (Fowler, 2014) (Newman)

ExampleThe distributor from the first chapter moves the delivery rules first: they change most often. For two months the new rules run next to the old ones and the results are compared. Then the old rules are switched off. Ordering and stock stay where they are for now.
  • Put each new piece live as soon as it works.
  • Keep a way back to the old piece until the new one has proven itself.
  • Switch off old parts as they are replaced.

How often can you put a change live?

Add a comment (optional)
Step 6

Let AI do the mechanical work, and check all of it

Once tests and small steps are in place, AI can take on the repetitive changes.

Moving code to a newer version of a framework, updating hundreds of similar places, drafting tests: that is where Google's migration gains came from, with people reviewing every change and undoing part of it. Keep the batches small and start where a mistake costs little. (Nikolov et al., 2025) (DORA, 2024) (Feathers, 2024)

  • One well-defined kind of change at a time.
  • Tests run on every AI change.
  • A named person approves what goes live.

How do you want to use AI here?

Add a comment (optional)
Step 7

Change the habits that let it decay

A modernized system decays again if nothing else changes.

Fowler's fourth activity is to change the organization so modernization can continue on an ongoing basis. (Fowler, 2024)

  • Tests with every change.
  • Knowledge written down next to the code.
  • Small, regular releases.
  • Time set aside for cleanup, every month.
Checklist

Ready to modernize step by step

A short list to go through with your technical lead.

  • The two or three outcomes are written down, with a way to measure them.
  • The main business rules are written down and checked by someone who knows them.
  • Tests record today's behaviour for the flows that matter most.
  • The first piece to replace is chosen, with a way back.
  • Changes go live in small steps, at least monthly.
  • AI changes are small, tested and approved by a person.
  • Cleanup time is planned, not left for later.
Your result

What this would look like for you

Not enough answers

Answer a few questions first

Go back through the guide and answer what you can. The plan fills in as you go.

Related guides

Rather not do it alone?

You can stop here and use the plan yourself. Or hand some of it to us. Pick how you'd like to work:

Your answers and comments come with your request, so we don't ask twice. You get a short proposal within two working days, starting with a fixed-price first step. No obligation.

Sources

  1. Ward Cunningham (1992). The WyCash Portfolio Management System. OOPSLA '92 Experience Report
  2. Adam Tornhill and Markus Borg (2022). Code Red: The Business Impact of Code Quality. A Quantitative Study of 39 Proprietary Production Codebases. International Conference on Technical Debt (TechDebt '22)
  3. Michael Feathers (2004). Working Effectively with Legacy Code. Prentice Hall
  4. Michael Feathers (2024). Working Effectively with Legacy Code and AI Coding Assistant (episode 195). Tech Lead Journal
  5. Joel Spolsky (2000). Things You Should Never Do, Part I. Joel on Software
  6. Martin Fowler (2024). Strangler Fig. martinfowler.com
  7. Martin Fowler (2014). Branch By Abstraction. martinfowler.com
  8. Sam Newman. Strangler Fig Pattern (from Monolith to Microservices, O'Reilly, 2019). samnewman.io
  9. DORA (Google) (2025). State of AI-assisted Software Development. Google Research
  10. DORA (Google Cloud) (2024). Accelerate State of DevOps Report 2024. dora.dev
  11. Thoughtworks (2025). Using GenAI to understand legacy codebases. Technology Radar
  12. Alessio Ferri, Tom Coggrave and Shodhan Sheth (2024). Legacy Modernization meets GenAI. martinfowler.com
  13. Stoyan Nikolov et al. (2025). How is Google using AI for internal code migrations?. arXiv (experience report)
  14. Thiyagu Palanisamy and Chandirasekar Thiagarajan (2025). From Black Box to Blueprint. martinfowler.com