Somewhere in your company there is a system nobody wants to touch. It books every invoice, it has run since 2012, and the last person who understood its batch jobs left three years ago.
That is legacy software. Most of it can be lived with for years, if you know which parts are about to fall off.
What is legacy software and where to find it?
After ten years and a couple of hundred thousand miles on the clock, a car is bound to have some issues. Every mechanical part has its limits.
Does it have to be scrapped? Not at all.
An experienced mechanic changes the parts that wear out, the timing belt and the brake pads, and the car runs happily for another hundred thousand miles. Software is surprisingly similar. A legacy system may creak a bit and need some refactoring, but most of the time it still does its job. What it needs is a good mechanic who knows which parts to replace and in what order.
Legacy software definition
On a more technical note, legacy software is a system that runs in production while some of its parts no longer get updates or support from whoever made them. It usually shows up in one of three ways:
- it runs on a platform, runtime or framework version that has reached end of support;
- it no longer meets current standards for security, compliance or how software is built and deployed;
- it cannot easily receive security patches, because the fix needs a newer version of something it depends on.
Our CTO, Arkadiusz Drysch, has a less formal definition:
Well, basically any system that has been deployed in production can be regarded as a legacy system, as it requires constant maintenance. There's no such thing in software development as write-and-forget architecture.
Arkadiusz Drysch, CTO, Stratoflow
He is only half joking. The moment code ships, the libraries under it start to age, and the team that wrote it starts to forget why it does what it does.
Legacy software in numbers: 2026
The best public numbers on legacy systems come from the US government, which has to report them. In July 2025 the Government Accountability Office reviewed the most critical federal systems (GAO-25-107795):
- the federal government spends more than $100 billion a year on IT, and agencies report spending about 80% of it on operations and maintenance of what already exists;
- the 11 systems GAO ranked most in need of modernization are between 23 and 60 years old and cost about $754 million a year to run;
- eight of the 11 use legacy languages such as COBOL and assembly, four run on unsupported hardware or software, and seven operate with known cybersecurity vulnerabilities;
- of the 10 critical systems GAO flagged in 2019, agencies had finished modernizing three by February 2025.
Private companies publish less, but the Java world gives a hint. In JetBrains' State of Java 2025, 31% of Java developers still use Java 8 regularly, a release from 2014. Six years earlier it was 83%, so the trend is right, but a third of the profession still works with code that predates most of what the platform can do today.
Why are legacy systems still used?
IT systems last for years, often decades, while the technology around them changes every few months. Companies are rarely surprised that a system is old; they are surprised when it loses support and needs real work. Here is why so many old systems keep running, with real examples.
1. They still do a huge job, and do it reliably
The US Social Security Administration processes retirement and disability claims with applications written decades ago. Its inspector general told Congress in 2016 that SSA maintained more than 60 million lines of COBOL, plus millions more in other legacy languages. Code at that scale encodes thousands of rules nobody has written down anywhere else, and it pays benefits correctly every month. Replacing it is not a weekend project.
2. Replacing them takes years, even when everyone agrees it must happen
In January 2023, contractors working on the FAA's Notice to Air Missions system accidentally deleted files while updating a database, and the FAA had to halt departures across the United States. After a failure like that, nobody argued about whether to modernize. The new NOTAM Management Service still took until April 2026 to take over from the old system: more than three years, with full political attention and a budget.
3. The budget goes to keeping the lights on
When about 80% of IT spending goes to operating and maintaining existing systems, as GAO reports for federal agencies, modernization competes for the remaining fifth with every new feature the business wants. The urgent wins over the important, year after year.
4. The code is the only specification
Many legacy systems have no up-to-date documentation of what they do. The behavior lives in the code, including the bugs customers have learned to rely on. Before anyone can replace such a system, someone has to work out what it actually does, and that is often the most expensive part of the whole exercise.
5. The upgrade keeps getting postponed
This is the Java 8 story. Each year the upgrade looks a little bigger than last year, so it slips again, until the system is two or three releases behind and the gap itself becomes the obstacle.
Where can you find legacy systems?
Government organizations and the public sector
Probably the most common habitat. Two of GAO's 11 most critical systems belong to the Treasury, both running on COBOL and assembly code, languages with a dwindling number of people able to support them, and the oldest system on the list, at Defense, is 60 years old. Hardware ages too: GAO found an agency system whose obsolete hardware has known vulnerabilities that cannot be fixed without modernization.
Banks, insurers and financial platforms
Core banking, payments, policy administration and accounting systems run for decades because they work and because the risk of changing them is real: they move money every second. Many of them are written in Java. FastPost, the accounting platform we developed for Legerity, went into production in 2013 and stayed in active development for nearly ten years, processing a billion financial transactions in under an hour (case study). A long-lived system is not a failure; an unmaintained one is.
Airlines and transport
Reservations, crew scheduling and air traffic information run on systems built when transaction processing was a mainframe job. The FAA's NOTAM system above is one example; our guide to legacy system modernization tells the story of Southwest Airlines' crew scheduling meltdown in December 2022.
Retail and ecommerce
You might expect online stores to be the most up to date of all. Often they are not, because the business measures sales, not stack versions, and the back office runs fine. An online wine merchant we worked with ran its store and back-office system on Java 17 and Spring 5.3, which no longer received open-source fixes, with 12 critical and 35 high-severity vulnerabilities in its dependencies (case study). It worked perfectly well, right up until the security scan.
Myths about legacy software
There are plenty of myths about legacy systems, and plenty of memes. Is there any truth in them? Time for a quick myth-busting session: the three classics first, then three we hear about Java in particular. Here is the verdict on each, before the details.
#1 Legacy software is unsupported
The IT market is not uniform, and neither is a legacy system. A typical business application stacks a runtime, a framework, a database, an operating system and a few dozen libraries, and each of them has its own support calendar. Some parts lose support years before others.
Java shows how far apart those dates can be. Free Temurin builds of Java 8 get security updates until at least December 2030 (Adoptium), while Spring Framework 5.3, which many Java 8 applications run on, left open-source support in August 2024 and stays covered only under a commercial subscription until mid-2029 (Spring support dates). The same application can be fully patched at the bottom and wide open two layers up.
Just as a mechanic may struggle to find parts for an older car, a developer may struggle with obsolete libraries and missing security fixes. So the useful question is never whether the whole system is supported, but which parts are not, and from which date. A one-page inventory answers it, and it is the first thing we build on any legacy project.
Myth: plausible.
#2 Legacy software is useless
A ten-year-old car still carries the same number of people and the same luggage as when it was new, even without the latest touchscreen.
Legacy systems are the same. They carry risks, which we cover below, but their core functionality does not wear out. Social Security's COBOL applications still process retirement and disability claims every month. FastPost, the accounting platform we developed for Legerity from 2013, kept processing a billion financial transactions in under an hour for nearly a decade.
The real value of an old system is rarely the technology. It is the business rules accumulated over years: every pricing exception, every regulatory change, every customer complaint that led to a fix. That knowledge is exactly what a replacement project tends to lose, and why replacements so often disappoint users on their first day.
Myth: busted.
#3 Legacy systems should be replaced immediately
A well-maintained used car keeps running. A well-maintained legacy system does too.
Replacing a system that works is one of the riskiest things an IT department can do. Queensland Health's payroll replacement was planned around a contract of about $98 million; fixing, maintaining and running what it delivered cost an estimated $1.2 billion over eight years, a story our legacy system modernization guide tells in full, along with TSB's failed banking migration. Even planned, funded modernizations take time: of the ten critical federal systems GAO flagged in 2019, three had been modernized by February 2025 (GAO).
The safer route is gradual. Find out which parts, tools and libraries have lost support or will lose it soon, and update them one at a time. Where a part really has to go, replace it in slices next to the old system, as the strangler fig pattern describes, so that every step can be tested and rolled back. The architecture will not win any beauty contests, but it will keep working throughout.
Myth: busted.
#4 Java itself is legacy technology
Java turned 30 in 2025, which makes it sound ancient. In practice it is one of the most used languages in the world: 29.4% of respondents to the Stack Overflow Developer Survey 2025 had used it in the past year.
It also changes faster than its reputation suggests. A new version ships every six months, the latest being Java 27 in September 2026, with a long-term support release every two years. The language a Java 8 developer learned has since gained records, pattern matching for switch, text blocks and virtual threads, and the newest version is now the most used one: Java 21 leads JetBrains' survey at 40%, ahead of Java 17 at 39% (State of Java 2025).
An old Java application is legacy. Java is not.
Myth: busted.
#5 Upgrading Java means rewriting the application
Java takes backward compatibility seriously. Bytecode compiled for Java 8 still runs on today's JVMs, apart from removed APIs and the JDK internals that Java 17 closed off for good (JEP 403). Business logic almost never has to change.
What does change is everything around it: build plugins, dependency versions, the javax to jakarta rename when the framework moves to Spring 6 or later, and the occasional library that was abandoned and needs a replacement. Much of that is mechanical, and tools such as OpenRewrite apply it with recipes that make the same change every time. Our article on AI-assisted application modernization covers where those tools and AI agents help and where they need supervision.
We moved an online wine merchant's store and back office from Java 17 to Java 25, with Spring and Jakarta EE upgraded along the way, in about four weeks. More than 800 files were changed by automated refactoring and every change was reviewed; 12 critical and 35 high-severity vulnerabilities were cleared, and the client's team kept shipping features throughout (case study). That is an upgrade, not a rewrite.
Myth: busted.
#6 Java 8 no longer gets security patches
For the JDK itself, it still does. Adoptium plans to build Temurin 8 with security updates until at least December 2030, Oracle's extended support for Java 8 runs to the same month, and other vendors sell their own long-term support. A Java 8 runtime can be kept patched for a few more years.
The catch is everything that runs on it. Spring Framework 5.3, the last generation that supports Java 8, left open-source support in August 2024, and Spring Boot 2.7 in June 2023. Fixes for them now come only with a paid subscription, and the same is true of many other libraries whose new versions need Java 11 or 17. Security scanners do not care which layer a vulnerability sits in.
A patched JVM under unpatched libraries is still a vulnerable application. If staying on Java 8 is the plan for now, budget for commercial support of the whole stack, not just the JDK, and put a date on the upgrade.
Myth: half true.
Why are legacy systems problematic? 3 most common problems
Of course, nobody would talk about replacing old systems if they caused no trouble. Every horror story about legacy code has a grain of truth in it. These are the three problems we meet most often.
- Cost. As Arek said, every system needs maintenance. A legacy system simply needs more of it, and the price per fix rises with age. Vendors charge premiums to support versions they would rather forget, specialists in old technologies are scarce and expensive, and every change takes longer because nobody is sure what it will break. GAO's figure of 80% of federal IT spending going to operations and maintenance is what this looks like at scale.
- Security. Libraries, frameworks and databases stop receiving security fixes for old versions a few years after release. Seven of GAO's 11 critical federal systems run with known vulnerabilities, and for at least one of them the fix requires modernization. For a small internal tool this is a manageable risk; for a system holding the personal data of hundreds of thousands of customers, it is the risk.
- Shortage of knowledge and experience. Universities teach current technologies, and developers move on to them. Each year fewer people know COBOL, Delphi or a framework that went out of fashion in 2012. SSA's inspector general put it plainly: the agency's workforce is "extremely proficient and experienced" but aging (SSA OIG). When the last person who understands a system retires, the system becomes a black box overnight.
Living with legacy systems: 3 tips from our experience
So, legacy software can be a pain, but it is still useful, and in many cases a new system is simply not needed. Here are three tips from our engineers on how to keep the headaches small.
#1 Keep track of the most important updates
In a legacy system the biggest risk is a component that loses support, so start with an inventory. For each part of the application, the team should be able to answer two questions: how long can it run on the current version, and how long will its critical libraries keep receiving fixes from their makers?
Then prioritize: the riskiest parts go to the top of the maintenance queue. For a Java system, that inventory lists the JDK, the framework generation and every dependency without a supported release; our Java end-of-life calendar has the dates for the JDK part.
#2 Don't rewrite what you don't have to, and finish what you start
A legacy system that does its job does not need a rewrite. It does benefit from regular refactoring and from small improvements where the code is changed anyway.
One rule matters more than the others: a refactoring has to be finished.
Say a developer starts rewriting the database access layer and gets 90% of the way. Nine requests out of ten now use the new, faster path, and the tenth still takes the old one. You now have two ways of doing the same thing, twice the code to understand, and a performance problem that only appears sometimes. That is worse than either version on its own.
Before changing anything important, write tests that pin down how the system behaves today, including the odd parts. They are what tells you that a refactoring changed the structure and not the behavior. AI tools can help draft such tests, as our article on AI-assisted application modernization describes, as long as an engineer checks them.
#3 Maintain good documentation, gather the necessary knowledge
Good documentation is a good habit in any project. In a legacy system it is a survival skill.
People come and go, and with an old system fewer of them know the technology to begin with. If the last developer who understands the nightly batch jobs leaves without writing anything down, the next team inherits a black box, and black boxes tend to get rewritten from scratch at great expense. Write down why the system does what it does, not only what it does: the business rules, the integrations, the jobs that run at 3 a.m. and the people who complain when they fail.
A practical trick from our projects: every time someone spends more than an hour working out how a part of the system works, the answer goes into the repository next to the code. Within a few months the scariest corners of the system have a map.
Keep, upgrade or replace? Four questions to decide
Living with a legacy system is often the right call, but not always. Sooner or later every system reaches the point where patching is no longer enough, and then the hard question arrives: what now?
The decision tree below, from our legacy system modernization guide, turns that question into four smaller ones. Two things make it work. First, go through it once per system, not once for the whole company: the invoicing engine and the customer portal rarely deserve the same answer. Second, every question is phrased so that yes means a bigger change, so the further down you go, the more the answer will cost.
Question 1: will the business need to change this system in the next two years?
This is the question that decides whether the system's design matters at all. Do not answer it from a strategy slide. Look at the change requests and tickets of the last twelve months: a system that got three small changes last year will probably get three small changes next year. A roadmap is the second-best evidence, a hunch the worst.
If the honest answer is no, the system only has to stay safe and running, which leads to question 2. If the answer is yes, it has to stay changeable too, which leads to question 3.
Question 2: is the system on unsupported or unpatched versions?
For a system nobody plans to change, this is the only question left. Check the inventory from tip #1 above: the runtime, the framework, the database, the operating system and the libraries with known vulnerabilities.
If something important is out of support, upgrade it in place: same design, newer versions, tested before release. If everything is still supported, keep and contain it, which is cheaper, but not free.
Question 3: does the system's design block the changes the business needs?
Most designs do not. A ten-year-old Java application with a reasonable structure can usually take new features for years, as long as its versions are kept current. In that case, upgrade in place and repeat the upgrade as new versions arrive, so the gap never grows into a project again.
Sometimes the design really is the obstacle: a nightly batch that the business now needs in real time, a data model that no longer matches how the company sells, a monolith where every release needs a week of regression testing. That is when question 4 comes in.
Question 4: could a packaged product replace the system?
Twenty years ago many companies built their own payroll, CRM or policy administration because nothing on the market fitted. Today something often does. If a product you can buy or subscribe to covers what the system does, replace it in stages: move one process, one region or one product line at a time, and switch the old system off only when nothing depends on it any more.
If no product fits, because the system is the thing that makes your business different, rearchitect it in slices with the strangler fig pattern: build the new version of one part next to the old system, route traffic to it, and retire the old part when the new one has proved itself.
What each answer means in practice
- Keep and contain still takes work. Put the system behind a stable interface so new code never talks to its internals, keep the runtime and the operating system patched, monitor the few things that would hurt if they broke, and write down what it does while the people who know are still around.
- Upgrade in place means weeks per application rather than months, with the code, the data and the behavior unchanged. The risk is low with good tests and high without them, which is why the tests come first.
- Rearchitect in slices takes months, spread over releases, and delivers value after the first slice rather than at the end. The price is a long middle period with two systems running side by side.
- Replace in stages usually takes a year or more, and the scope tends to grow as hidden business rules surface. Doing it in stages is what keeps a bad surprise from turning into a TSB-sized outage.
Whatever the answers, put a date in the calendar to ask the four questions again next year. Systems drift, businesses change direction, and a system that only needed containing last year may need an upgrade now. For a company with dozens of systems, the order in which to work through them matters as much as the answer for each; our guide to application modernization covers how to plan a whole portfolio.
Upgrading Java to a modern version: why it is worth it, and what to watch out for
For many companies, the legacy system they actually have is a Java application a few releases behind. That is good news: of all the kinds of legacy, it is one of the easiest to fix.
Why it is worth it
- Speed and memory you get without changing code. Compact object headers cut heap use by 22% on SPECjbb2015 in the JEP's own measurement (JEP 519), and the AOT cache started Spring PetClinic 42% faster (JEP 483). Garbage collectors and the JIT improve with every release.
- Virtual threads (JEP 444, Java 21) let a service that mostly waits on databases and other services handle far more concurrent requests with simple, blocking code.
- Supported libraries. Spring Boot 3 and 4 require Java 17 or later (Spring Boot system requirements), so the JDK upgrade is also the door to framework versions that still receive security fixes.
- Better diagnostics. Recent JDKs ship profiling and monitoring tools that older ones lack; our guide to Java profilers lists what each release added.
What to watch out for
- Removed APIs. Java 15 removed the Nashorn JavaScript engine (JEP 372), and Java 24 permanently disabled the Security Manager (JEP 486). Code that used them needs a replacement first.
- JDK internals. Since Java 17, libraries can no longer reach into JDK internals (JEP 403); old versions of some libraries break and have to be updated.
- The javax to jakarta rename. Spring Framework 6 and Spring Boot 3 moved to Jakarta EE, so every javax import of the enterprise APIs changes. Tools such as OpenRewrite do most of it automatically.
- Dependencies without a newer version. Some old libraries were abandoned; they need a replacement, which is real work and should be found early.
What not to do
- Do not combine the upgrade with a rewrite or a redesign. Change one thing at a time, so that when something breaks you know why.
- Do not upgrade without tests that cover what the business depends on. The wine merchant's tests caught two breaks before release, one of which would have stopped all PDF generation.
- Do not jump straight to every new runtime feature. Upgrade, compare performance with a baseline, then switch on features such as compact object headers one at a time.
- Do not wait for the next end-of-support date. A release or two behind is a few weeks of work; four releases behind becomes a project.
Java 25 is the current long-term support release and the natural target in 2026. Support dates and the real cost of an upgrade are in our Java end-of-life calendar.
If your legacy system runs on Java and you would rather have a mechanic who has done this many times, our application modernization team starts with an inventory and a written ballpark, then upgrades the system in tested steps while your team keeps shipping.