The hidden costs of legacy applications sit below the waterline. Everyone knows old software is expensive to live with, and that maintenance bill is a shark's fin above the surface. What actually bites is underneath, absorbed into normal operations, which is why nobody defends it and nobody pays it down.
What makes a cost hidden
A cost becomes hidden when no line item names it and no one owns it. In my experience there are three ways that happens, and the mechanism matters more than the individual cost, because the mechanism is what keeps it out of sight.
The first is that the cost lands in someone else's budget. The legacy application's own numbers stay flat while the money surfaces elsewhere, as support headcount in one place and as extra weeks on an unrelated project in another. Engineering looks efficient, because the spending moved somewhere else and kept going.
The second is that the cost never arrives as an event. Organizations notice money when it turns up as something, an invoice, an incident, a project request, a line in next year's plan. A cost spread thinly across every working day, a few extra minutes here and a slightly padded estimate there, never presents itself for approval, and there is no day you can point at as the day it started. Judging it would mean knowing what the number should have been, and that figure has never existed.
The third is what does not happen because the old system is in the way. The order that was never placed, the report that was never built, the request somebody talked themselves out of. There is no accounting entry for a thing that did not happen, so this kind of cost is invisible from the start.
The first of those three deserves the most attention, because it is what protects the system from scrutiny. A legacy application's own line item usually looks reasonable, and nobody proposes replacing something that appears to be under control. So the spending grows in operations, in support, in the contingency on every project that has to integrate with it. The bill is real. It has simply landed where nobody is connecting it back to the cause.
Maintenance is the biggest part of systems cost. The US Government Accountability Office reported in mid 2025 that roughly $83bn of $105bn in planned federal IT spending for that year was going to operations and maintenance. That figure covers federal agencies, though anyone who has tried to fund a rewrite will recognize the shape of it.
A limp you stop noticing
I run marathons. I once developed a wart in an uncomfortable place on my right foot, and I started putting more of my weight on my left leg to keep the pressure off it. I carried on running like that.
The foot healed eventually, though the altered gait stayed with me a while longer, and it took some deliberate work to get back to running normally. Once I did, my speed and endurance started improving again.
While I was compensating, I had no sense of losing anything. The gait had become how I ran, and the slower times had become my times. Legacy systems do the same thing to an organization, and the four costs below are all versions of a limp that stopped registering as one.
The people who will still maintain legacy code
The first hidden cost is the steady shrinking of the group who are willing to change the system.
We had a client running an old version of Java with Struts, and hiring for it taught me something I had not expected. Very few candidates had Struts anywhere on their CVs. The few who did were often not the developers we had hoped to find, and almost everyone we spoke to wanted to work on Spring.
The detail that stayed with me is that many Java candidates stopped showing up after the first interview round. They took the call, heard what the work involved, and quietly went elsewhere. Nobody told us the stack was the reason, so there was nothing to record and nothing to escalate.
Others see the same pattern. Stack Overflow's 2024 developer survey found technical debt to be the top frustration at work, cited by 62% of respondents and running at roughly double the next item on the list.
What the shortage actually does
Fewer willing hands means knowledge concentrates. Over time the group who can safely change a given part of the system narrows to three people, then to one. When that person is on leave, change stops, and urgency does not alter that. When they resign, you find out how much of the system was documented only in their head.
There is a quieter version of the same problem too. When one person is the only one who understands a piece of logic, their judgement that it is too fragile to touch cannot be checked by anyone else. That judgement may be entirely right, and you have no way of finding out, so it stands.
The cost here is everything that did not happen, and it stays hidden because the evidence walks away. You never meet the candidates who read the job description and closed the tab. You never hear the proposal that someone talked themselves out of in a corridor, once they had worked out whose approval it would need.
To see it in your own organization, look at the reasons recorded on declined offers, at how long it takes to fill a role on the legacy team compared with your greenfield team, and at whose name turns up on every incident bridge.
That narrowing shows up next in something the business does feel, which is the price of every change.
The price of not knowing what the code does
The second hidden cost is that uncertainty about the code gets priced into every estimate, and the business makes its decisions against that price.
The estimate has to carry everything nobody knows. Where documentation is thin and the people who wrote the code have moved on, an honest estimate covers the possibility that a small change reaches into three places nobody expected. That produces a big number, and in my experience it produces a round one. Forty hours.
Sometimes it really is forty, though more often it comes in under, because the complication everyone feared turned out not to be there.
By then the number has done its work. The business saw forty hours, weighed it against everything else competing for the same budget, and decided this particular change was not worth it. Nothing in that decision gets recorded as a cost of the legacy system. It reads as ordinary prioritization, which is exactly what it looks like from the inside, and no invoice is ever raised for it.
The uncertainty follows directly from the shortage described above. When few people hold the knowledge, the size of an estimate depends on which of them is available and on what they remember about a module they last touched three years ago.
You can go looking for it anyway. Take your last twenty completed items and compare estimate against actual. Actuals landing consistently under tells you how much of your planning number is padding, and once you know that, you can ask what else got turned down against numbers of the same kind.
So the business asks less.
The feature requests that were never made
The third hidden cost is the work the business stopped asking for.
A request that gets declined against a forty-hour estimate at least exists. Someone wrote it down, someone weighed it, and there is a record of the decision. What comes after that is quieter.
Once enough of those conversations have gone the same way, people stop starting them. They have learned what the answer will be and they save themselves the meeting.
The backlog looks healthy. Ticket volumes are manageable, engineering is responsive, and nothing in the numbers suggests a problem. Absence of demand reads as satisfaction.
This is the purest hidden cost of the four, because the evidence is a set of conversations that never happened. You cannot count them, and surveying for them is unreliable, since people rarely remember deciding not to ask.
I stopped asking too
I know the pattern from the inside, because I was the one who went quiet.
We had a home-grown metrics reporting system, built in-house and then left to stagnate while client work took priority. For a while I would ask for changes, a new metric or an adjustment to an existing one. Then I worked out that nothing would move until the system was rebuilt, and I stopped raising them.
None of that reached anyone. I escalated nothing and complained to no one, and after a while the requests stopped forming into anything I would have taken to a colleague.
We eventually adopted Power BI with a consistent ETL process behind it, and before long the same reporting was available again. What I remember most is how it felt to ask for a change and watch it get implemented quickly. The requests I had stopped making came back immediately, because they had been sitting there the whole time.
I have seen the same reversal at client companies. When an organization finally clears the debt, feature requests start streaming in, and they arrive as though a queue had been waiting.
Which means the only reliable measurement is retrospective, and you get it after paying to fix the problem. Before that, the nearest approximation is to ask three or four business leads what they have wanted for the past two years and never formally requested, then compare that list against your backlog.
The gap between those two lists is the cost of the blockage. That demand still has to go somewhere.
The spreadsheet layer
The fourth hidden cost is the manual work that grows to fill the gap the system leaves. Suppressed demand does not evaporate. The work still has to get done, so people build the missing capability somewhere they can reach. A spreadsheet, an Access database, a scheduled export that somebody massages by hand every Monday morning.
Our own operations teams ended up working this way, and so did our Project Resourcing team. Changes to the system were not going to happen, so the work moved into spreadsheets. There were a lot of them.
The frustrating part was populating them. Numbers that a system should have produced were being assembled by hand, every cycle, by people whose job was something else. We resolved it by recreating the functionality in systems that are properly maintained now, though for a long while before that the spreadsheets were how the work got done.
Those hours sit in the operations budget. The legacy system's own numbers stay flat, and this is the cost landing in someone else's ledger, which is the first of the three mechanisms and the easiest one to miss from a technology seat.
To find yours, ask an operations team to walk you through a routine task and count how many times they leave the system. Then ask who maintains each file they open.
Why the loop holds
Here is the part that keeps all four costs in place.
The spreadsheets work. Reporting gets produced and resourcing decisions get made. The system passes inspection, because every gap in it has been quietly filled by someone doing manual work, and nobody writes a business case against a spreadsheet that is doing its job.
So the shortage of people willing to work on it continues, estimates stay large, the business keeps not asking, and more work moves into spreadsheets. Each turn of that loop makes the next turn more likely, and every individual decision along the way is defensible.
What AI changes about clearing technical debt
There is a reason that loop has held for so long. The usual argument for tolerating technical debt is that clearing it costs more than living with it.
AI-assisted development has moved that calculation, and in our own work I have watched it move. Two things used to put a rewrite out of reach. You had to read a great deal of unfamiliar code, and you had to write the tests that make a refactor safe. Both are much faster now. A rewrite that would have been out of reach a few years ago now sits inside the range where a CTO can reasonably argue for it.
Stack Overflow's 2025 survey found 66% of developers naming AI output that is almost right as their biggest frustration, with 45% reporting that debugging AI-generated code takes longer than expected. Those numbers describe a solvable problem. The frustration falls away where developers and architects understand the problem well enough to judge what comes back at them. Planning the work step by step before generation starts helps, and so does reviewing everything that comes out of it.
The parts that were always hard are still hard. Somebody has to decide the work is worth doing and carry it through approval. That part still runs at human speed.
The gait you stop noticing
Nobody is going to escalate a hidden cost, because from the inside it reads as how things are. It becomes visible at the moment you remove it, which is an awkward property for a cost to have, since the evidence only arrives once you have already committed to the spend. My own foot was the same. The loss only showed up once the gait went back to normal and the numbers started improving.
That leaves you making the case on smaller signals. A role that has been open for five months. An estimate that came back at forty hours and finished in twenty. A resourcing team that opens a spreadsheet before it opens the system. Each of those is easy to explain away on its own, and together they describe a limp.
So here is the one thing worth doing this week. Pick the system you have quietly stopped asking for changes to, and go and ask the three or four people who depend on it what they gave up on. Those answers are missing from your backlog.
What have you stopped asking your own systems for?
If that turns up something worth acting on, our Legacy App Modernization work is where we would pick it up.






