Skip to content

Technical Debt Explained for Managers: The Cost of Waiting

Technical debt explained in business terms: what the interest costs you, how it shows up in delivery times and bugs, and how to pay it down safely.

By

Freelance full-stack developer

Published
Reading time
12 min
In this post9

Technical debt is the extra cost you pay on every change to your software because of shortcuts, outdated parts and cleanup that never happened. Explained in business terms, it works like a loan: you got something shipped sooner, and now you pay interest in slower delivery and more bugs until someone pays down the principal. Waiting doesn't shrink the debt: it only makes the interest feel normal.

I'm a freelance full-stack developer in Denmark who maintains and extends existing web apps, so I'm not neutral here. The goal of this guide: you should be able to discuss technical debt with your developers or agency without reading any code.

The short answer

If you understand a business loan, you already understand technical debt. Programmer Ward Cunningham introduced the metaphor in 1992, and more than three decades later it's still the most useful way to explain the problem to anyone who manages a budget.

How technical debt maps to a business loan
Business loanTechnical debt
PrincipalThe amount you borrowedThe cleanup needed to make the code easy to change again
InterestWhat you pay each month to carry the loanThe extra hours every feature and bug fix takes because of the mess
Compound interestUnpaid interest is added to the balanceNew code is built on top of old problems and inherits them
RepaymentPaying down the balanceRefactoring and adding tests where the code changes most
Good debtBorrowing for something that pays for itselfA deliberate shortcut to hit a launch or validate an idea
DefaultInterest eats all your incomeNearly all development time goes into keeping the system running

The decision rule is simple: you don't need zero debt, but you need to know where it sits and pay the interest on purpose, not by accident. If the same kind of task costs noticeably more than it did a year ago, interest is piling up somewhere. Technical debt is one thread in a longer story, which I follow from first idea to live product in my guide to the software development process.

What the metaphor gets right, and where it breaks

Martin Fowler, a well-known author on software design, has a worked example I use a lot. A new feature would take 4 days in clean code but takes 6 because the surrounding module is confusing. Those 2 extra days are the interest. Cleaning up the module might take 5 days, which isn't worth it for one feature. If a couple more similar features are on the roadmap, the math flips. His short explanation of technical debt is worth reading in full.

The loan comparison has three gaps that matter to managers:

  • Nobody sends you a statement. Technical debt stays invisible unless someone writes it down.
  • The interest rate depends on location. Messy code nobody touches costs nothing. The same mess in your checkout flow costs you on every change.
  • The lender can call the loan at any time. A security hole goes public, a payment provider retires an old API, or the one developer who knows the system leaves. Then you repay on someone else's schedule.

Four kinds of debt

Fowler sorts debt by two questions: was it taken on deliberately, and was it a sensible call? His technical debt quadrant gives four types:

  • Deliberate and prudent: "We ship now and clean up after launch." A fair trade if "after launch" actually happens.
  • Deliberate and reckless: "We don't have time to do it properly." Usually the most expensive kind, because the interest arrives sooner than anyone expects.
  • Inadvertent and reckless: the code was written by people who didn't know better. It's common in systems built on the cheapest bid.
  • Inadvertent and prudent: only after a year or so of work on a project do you understand how it should have been built. This kind is unavoidable and perfectly normal.

What technical debt isn't

Bugs aren't debt. A bug is wrong behavior today, while debt makes tomorrow's change expensive (although debt tends to breed bugs). Old technology isn't automatically debt either: a ten-year-old system can be well built and cheap to run. And missing features belong on the wishlist, not in the debt ledger.

How debt builds up in a normal project

Hardly anyone creates debt out of laziness. These are the usual sources:

  • Deadline pressure. An investor demo or a big customer waiting, and the fast fix beats the right one.
  • Requirements that moved. The system was designed for how you worked two years ago. That's normal, and it's one reason I prefer building in small increments, as I explain in agile vs waterfall.
  • No automated tests. Without them, nobody dares to clean up, because nobody can tell what breaks.
  • Outdated dependencies. Frameworks and packages that aren't kept current get harder to upgrade with every release. I cover the details in why you should update software dependencies.
  • Many hands, no shared direction. After a few developers or agencies have taken turns, you often find three different ways of solving the same problem.
  • Knowledge in one head. Anything only one person knows falls due the day they leave, which is a real risk if you rely on a single developer or a small agency.

How it shows up in delivery times and bugs

You probably don't read the code, but you do see the symptoms. These are the ones I'd watch:

  • Estimates for the same kind of work keep growing. What took a week last year takes three now.
  • Tickets sit at "almost done": the change itself is quick, but testing and releasing drag on.
  • Fixing one thing breaks another, and bugs you paid to fix come back.
  • Releases get rarer and more nervous, with an unwritten rule against deploying on Fridays.
  • Only one developer dares touch certain parts, and new hires take weeks to become useful.
  • Simple-sounding requests get answered with "that needs a bigger rebuild."

DORA, a research program that studies how software teams deliver, tracks this kind of signal. Two of its core metrics are change lead time (from committed code to production) and change fail rate (the share of deployments that need immediate intervention). Its finding is that speed and stability aren't a trade-off: the strongest teams do well on both (DORA's software delivery metrics). Technical debt pushes both numbers the wrong way.

How big is the bill? In a 2018 survey commissioned by Stripe with more than 1,000 developers, respondents estimated that the average developer at their company spent 13.5 hours a week on technical debt, out of a roughly 41-hour week (Stripe, The Developer Coefficient). These are self-reported estimates, but the order of magnitude matters: the interest is not a rounding error.

For a structured check of your own system, my list of signs of a healthy or unhealthy codebase works without a technical background.

What waiting really costs

The tricky thing about technical debt is that it never sends an invoice. Everything just gets a little slower, gradually enough to feel normal.

Take a made-up example. Your product gets 80 hours of development a month, and a fifth of that goes to working around old code, fixing avoidable bugs and testing by hand. That's 16 hours a month of interest, close to 200 hours a year, before anything new gets built. Multiply by your hourly or day rate and you have a number your CFO will understand. The figures are invented; the calculation works with your own.

The interest also compounds:

  • New code inherits old problems. Five features built on a shaky module means five places to clean up instead of one.
  • Outdated parts get harder to upgrade with each release, until the old version stops getting security fixes.
  • Knowledge fades. The longer you wait, the fewer people remember why the code looks the way it does.

For businesses in the EU there's a compliance angle as well. If the system processes personal data, GDPR Article 32 requires security appropriate to the risk, taking the state of the art into account. In my view, running components that no longer receive security patches is hard to square with that.

The biggest cost rarely shows up in any report: the opportunities you pass on. When a prospect asks for an integration and the honest answer is "three months," you may be saying no to revenue.

How to pay it down without stopping feature work

You don't need a feature freeze. Treat it like paying off a loan: a fixed installment every month, plus extra when there's room.

  1. Put the debt on paper. Ask your developers for a short debt register: the area, what it costs day to day, and a rough cleanup estimate. A spreadsheet you can read too is plenty.
  2. Measure the interest. For a couple of months, track how far actual hours drift from estimates and how many bugs follow each release.
  3. Prioritize by interest, not by ugliness. The expensive debt sits where the code changes often and where failures hurt: payments, login, invoicing. Messy but stable code that nobody touches can stay, which is also Fowler's advice.
  4. Repay continuously. My rule of thumb is a fixed share of development time for cleanup, typically 10-20%, plus tidying up whatever area you're already working in.
  5. Build the safety net first. Before any larger cleanup, the critical flows need automated tests so you can see when something breaks. I make the business case in why automated testing saves money.
  6. Stop new debt at the source. When you take a shortcut on purpose, write it down with a plan for when it gets repaid.

Refactor, rewrite or live with it

Once the debt is large, someone will suggest starting over. My answer is almost always no, at least not in one go.

  • Refactoring (improving the code without changing what it does) is the default: the system keeps running and the risk stays low.
  • Replacing piece by piece fits when one part is beyond saving: build a new module alongside the old one and move functionality over gradually.
  • A full rewrite is the last resort, for example when the technology is truly dead or the business has changed so much that the system solves the wrong problem.

Sometimes living with the debt is the right call: when the system will be retired within a year, when a first version is still proving the idea (as long as you know the bill comes due if it works), or when the messy part almost never changes.

When you don't need outside help

Fixing this kind of thing is part of how I make a living, but you shouldn't hire someone like me if:

  • you have an in-house developer with time and experience. Give them room to repay rather than bringing in someone who has to learn the system first.
  • the debt is in a stack I don't work with. I work with Laravel, PHP and JavaScript (React and Next.js), so for .NET or Java you want a specialist.
  • the real problem is that nobody agrees on what the system should do. Cleanup won't fix that.
  • it's a SaaS product you subscribe to rather than own. Then it's the vendor's debt, and your decision is whether to stay or switch.

Next steps

Start by getting the debt written down. Take the questions below to your next meeting with your developer or agency, and ask for the five biggest debt items with a rough estimate of the interest on each. That gives you what you need to prioritize, whoever ends up doing the work.

Questions to ask your developer about technical debt

  • Debt register: is there a written list of the biggest debt items, and when was it last updated?
  • Interest: which parts of the system slow down new work, and by how much?
  • Tests: are critical flows like login, payments and core processes covered by automated tests?
  • Versions: do the framework and language run on versions that still receive security fixes?
  • Repayments: what share of development time goes to cleanup today?
  • Deliberate shortcuts: are the shortcuts you chose documented with a repayment plan?
  • Key-person risk: are there areas only one person can work on?

If you don't have a regular developer, or you want a second opinion on your system, see how I handle maintenance and ongoing development for existing web apps. You work directly with me, the person writing the code, you own the code from day one, and you'll get a reply within one business day.

Frequently asked questions

How do I explain technical debt to my board or CFO?

Use three numbers instead of technical detail. First, the interest: hours lost each month to working around the code, priced at your rate. Second, the principal: a rough estimate of what cleaning up the worst areas would cost. Third, the call risk: what happens if a key component loses support or a key person leaves. Framed like that, repaying debt becomes an ordinary investment decision instead of a developer wish.

Does AI-generated code create technical debt?

It can, and often faster than hand-written code. AI tools are good at producing code that works right now, but they don't know the rest of your system and tend to repeat solutions instead of reusing what's already there. Without tests and a developer reviewing the output, debt builds quietly. In the hands of an experienced developer with a good test suite, the same tools are a real help.

Can a tool measure technical debt?

Partly. Static analysis tools can flag complex code, duplication and outdated packages, and they're useful for tracking trends over time. What they can't see is which parts cost you money, because they don't know what changes often or what's business critical. Treat them as a thermometer, not a priority list. Delivery time and the number of bugs after each release remain the better measures.

Should debt repayment be part of a maintenance agreement?

Yes, at least the parts that cover updates and security. A good agreement states how often frameworks and packages are updated and how cleanup is weighed against new work. Repaying larger debt items usually works best as a fixed share of the hours you already buy, so it doesn't have to be renegotiated every month. Without that, cleanup tends to lose to whatever feels urgent.