Technical debt works better as a loan book, and the missing column is the interest rate
In a study published in the Journal of Systems and Software in 2019, 43 developers reported twice a week, for seven weeks, how much of their working time technical debt had cost them. The mean was 23.1%. The median was 17.1% and the standard deviation 21.1%, nearly as large as the mean, and six developers said they had lost more than half their time. Averaged by employer, the figure ran from 18.1% at one company to 51.5% at another. Terese Besker, Antonio Martini and Jan Bosch, who ran the study, were collecting self-reports. They show that the cost is large somewhere, and the gap between employers shows that the answer changes with the codebase, so no industry average can stand in for your own measurement.
I think the debt metaphor should be taken more literally than most teams take it. Engineering teams talk about debt, interest and paydown, and few keep the books that vocabulary implies. My thesis is that every item of technical debt belongs in a register with three quantities: a principal (the hours to repay it), a monthly interest (the extra work it adds each month) and an expected life (how long the code will exist). Interest divided by principal gives a rate. Repayment then becomes a capital allocation decision, ranked against other uses of the same hours by payback period. Borrowing on purpose to learn something stays rational under this view. The thing to go after is unmeasured interest, since without a number every repayment discussion goes to whoever argues loudest.
The scope is engineering management. Sculley and colleagues described the machine-learning variant in 2015, which has its own essay on this site, and the register applies there too. Below I start from what Cunningham meant, add Fowler and McConnell, work through an example with made-up numbers, check what the published measurements support, and then take up the best objection.
Cunningham borrowed to learn, and said so twice
The metaphor comes from a short experience report that Ward Cunningham wrote for OOPSLA in 1992 about WyCash, a portfolio management system for cash securities. He compared releasing first-time code to going into debt. A little debt, he wrote, speeds development as long as it is repaid promptly with a rewrite, and every minute spent on not-quite-right code counts as interest. The danger he named was non-repayment: too much unconsolidated code makes a program unmasterable, pushes programmers into extreme specialization and leaves an inflexible product. The same passage makes a point that is quoted less often. He described the traditional waterfall method as payment up front and in full, and he preferred incremental growth, which he called feasible and desirable though not always comfortable. Read this way, the 1992 report is about financing: it asks when a team should pay for understanding, before the code or after.
In 2009 he recorded a short video to correct how the idea had been read, and transcripts of it circulate online. He said he coined the metaphor to explain to his boss why the team was refactoring the program so that it matched what they had learned about financial objects. Failing to do so meant stumbling over the mismatch repeatedly, which slowed the team the way interest slows a borrower. He considered borrowing a good idea and rushing software out to gain experience a good idea too, provided the learning was later put back into the code. If it never was, the interest eventually consumes everything, and he described a program that only gains features until it no longer contains any understanding and every change takes longer.
He then addressed the misreading directly. Bloggers, he said, had taken the metaphor to mean writing code badly on purpose and fixing it later. He had never favored writing code poorly. What he favored was code that reflects your current understanding, even when that understanding is partial, and he added that the debt works to your advantage only if the code is clean enough to refactor once you learn more. A team that borrows therefore has to leave behind code whose intent a reader can follow, because the repayment is a refactoring and a refactoring needs a clear starting point.
Martin Fowler's quadrant, published in October 2009, sorts debt along two axes: deliberate or inadvertent, prudent or reckless. He placed the kind Cunningham described in the prudent and inadvertent corner, the debt that arrives because even good teams only see the better design after they have built the system. Prudent and deliberate debt, a conscious trade of a later cost for an earlier release, is also in the scheme. A mess is reckless debt in his terms, and he said it produces crippling interest. The distinction decides what belongs in a register. A loan taken to learn has a purpose, a repayment path and a price. A mess has none of them, and calling it debt dresses an accident as a decision. I would handle a mess as a quality problem and keep the register for items someone could defend as a choice.
Interest accrues on use, so an untouched module costs nothing
Fowler's 2003 post on technical debt, rewritten in 2019, gives the clearest working definition. The extra effort every new feature needs because of poor internal quality is the interest, and cleaning up is paying down the principal. His next point matters most for allocation. Interest is paid only when you modify the affected code, so cruft in a stable corner of the system can be left alone, and attention belongs where activity is high. He also marks where the metaphor breaks: real interest accrues with time, and this interest accrues with use.
That gives a formula. Monthly interest equals the number of changes per month multiplied by the extra hours each change takes. A hideous module that nobody touches pays no interest, while a mildly awkward one that every team touches daily can be the most expensive item on the books. Principal enters the decision as the price of eliminating that stream. Interest per month over principal is the monthly rate, and principal over interest is the payback period in months.
Steve McConnell's 2008 white paper for Construx adds three practical points. The cost of a shortcut is the quick path, plus the good path later, plus the cost of ripping the quick path out, so the true price of borrowing is higher than the shortcut's visible saving. Some of what teams call interest is a late fee, a one-time cost of replacing the code, while the real interest is the ongoing slowdown of related work. And there is often a third option, a quick path isolated so that it slows nothing else, which carries an interest rate near zero. McConnell also asked teams to keep a debt list with an estimated effort for each item, to treat any item unresolved after 90 days as critical, and to refuse shortcuts too minor to be logged. For repayment he suggested spending the first iteration after a release on short-term debt. His rules are keyed to elapsed time. The payback rule below is keyed to what the interest costs.
Borrowing on purpose can be the cheaper path
Take a made-up example. A team can build a feature the good way in 160 hours, or the quick way in 60. If the feature survives, the quick version will be replaced by the good one at a cost of 160 hours plus 20 for ripping out the old code. While it lives, the quick version adds 2 extra hours to each change, and three changes a month make 6 hours of interest. Suppose it survives and is replaced after six months. The total is 60 + 180 + 36 = 276 hours, which is 116 more than the 160 the good path would have cost. Suppose instead the feature is dropped after three months because users did not want it. The total is 60 + 18 = 78 hours, a saving of 82.
The loan is therefore a bet on whether the feature survives. It breaks even when the probability of abandonment is 116 / (116 + 82), about 59%. If the team puts the odds of dropping the feature at 30%, the expected extra cost of borrowing is 0.7 × 116 − 0.3 × 82 = 56.6 hours. Now assume the quick version ships three weeks earlier, a figure the example does not derive and which depends on the team. Borrowing is then worth it when each week of earlier user feedback is worth more than about 19 engineer-hours. For a product whose main uncertainty is whether anyone wants the feature, that is a low bar. For a feature certain to stay, it is a high one, since the payoff from shipping early comes from the chance of never paying the repayment cost at all.
Cunningham's condition shows up in the arithmetic. I assumed that ripping out the quick code costs 20 hours, which holds if the code is clean and reflects what the team understood. If the quick path is a tangle that has to be rewritten, set the ripping-out cost at 160 hours. The survival case then costs 416 hours, 256 more than the good path, and the break-even probability of abandonment rises to 76%. The same shortcut is a sensible bet at one level of craft and a poor one at another, which is the practical meaning of his insistence on code clean enough to refactor.
Fowler's Design Stamina Hypothesis, from 2007, bears on the horizon. He proposed that the point where good design starts to beat no design in cumulative delivered functionality comes in weeks, not months, and by his own account it is a conjecture, since productivity and design quality are hard to measure. If it holds, loans should be small and short. If the crossover is closer to months for your team, the example above should be rerun with longer interest periods and the break-even shifts accordingly. I cannot tell you which holds for your codebase, and neither can Fowler's post.
A register needs five fields per item
I would keep the register to a page, with these fields for each item:
- Principal: the hours to repay the item in full, estimated by the people who would do the work, as a range if they disagree.
- Changes per month: how often the affected code was modified over the last two quarters, taken from version control.
- Extra hours per change: the added time compared with a comparable change elsewhere in the system.
- Expected life in months: how long before the code is retired or replaced for other reasons.
- Reason and owner: what was learned or bought by borrowing, and who decides on repayment.
From these, monthly interest is changes times extra hours, and payback is principal divided by interest. The rule I propose has three tiers, with thresholds you should set from your own alternatives. An item whose payback is under six months and under its expected life is repaid without further debate. One whose payback is between six and twelve months competes for the quarter's repayment budget, ranked by payback. Anything over twelve months, or longer than its expected life, waits and stays on the books. The twelve-month ceiling should equal the payback you demand of a feature or infrastructure project, because a repayment competes with those for the same hours.
Here is an illustrative register, again made up, with a repayment budget of 200 hours for the quarter.
| Item | Principal (h) | Interest (h/month) | Monthly rate | Payback (months) | Life (months) | Decision |
|---|---|---|---|---|---|---|
| Checkout lacks integration tests | 80 | 15 | 18.8% | 5.3 | 36 | Repay now |
| Hand-rolled billing retries | 120 | 15 | 12.5% | 8.0 | 36 | Repay, fits budget |
| Hard-coded roles in admin tool | 60 | 6 | 10.0% | 10.0 | 24 | Waits, budget spent |
| Order module boundaries | 600 | 48 | 8.0% | 12.5 | 36 | Waits, revisit |
| Legacy report generator | 200 | 4 | 2.0% | 50.0 | 12 | Leave alone |
The order module has the biggest interest bill by far, 48 hours a month against 15 for the next item, and it is still not first in line. It costs 7.5 times as much to repay as the checkout tests while its interest is only 3.2 times as high. Over its 36-month life it would save 1,128 hours net of its principal, more than any other item, so ignoring it would be a mistake. The problem is capital rationing, as in any budget: with 200 hours available, the checkout tests and billing retries return 880 net hours between them, and the order module cannot be bought at all in that quarter. A staged repayment is the sensible response: a first slice that removes part of the interest for a fraction of the principal. The legacy report generator has a payback of 50 months in code that will be gone in 12. Its line in the register records a decision to do nothing, and that record is worth having.
Estimates will be wrong, so I tested how wrong they can be. I multiplied each interest figure by a random factor between one half and two, ran 10,000 draws, and applied the same rule. The report generator and the order module were never funded. Funding frequency was about 91% for the checkout tests, 67% for the billing retries and 39% for the admin roles, and the average net saving came to roughly 735 hours against 880 with perfect numbers, about 83%. Funding items in random order within the same budget averaged about 440 hours. Errors of a factor of two cost about a sixth of the value, and ignoring the numbers cost about half. Because the inputs are invented, the simulation shows only that a rule of this shape tolerates noise of that size.
Measure interest on your own tickets, because surveys will mislead you
Published figures show how loose the available estimates are. Besker and colleagues' 2019 paper reports a mean of 23.1% in its 43-developer panel and, in a replication using 177 work items reported by 47 developers at a single company, a mean of 28.5% with a median of 20%. An earlier study that the paper cites, with 258 survey respondents plus 32 interviews, produced an estimate of 36%. Testing was the most common extra activity in the panel. On 24% of reporting occasions developers said that existing debt had forced them, at least to a very small extent, to add new debt, and on 3% of occasions to a great extent. That last result matters for the register, because interest does not hold still: workarounds create further workarounds. If the 15 hours a month on the checkout tests grew by 3% per month, a made-up rate, the 36-month cost would be 949 hours instead of 540. A deferred item can cost more than its first estimate said, which is a reason to re-price the register every quarter.
Stripe's 2018 report The Developer Coefficient, produced with the Harris Poll from a survey of more than 1,000 developers and more than 1,000 C-level executives, gives a 41.1-hour developer week. Of that, respondents estimated 17.3 hours a week wasted on maintenance, which the report's chart splits into 13.5 hours of technical debt and 3.8 hours of bad code. These are respondents' estimates, and the report comes from a payments company that presents its findings as a case for using developers better. The 17.3 hours are 42% of the week, and a 2022 paper by Adam Tornhill and Markus Borg cites Stripe for the claim that technical debt may waste up to 42% of developers' time. In Stripe's own chart the technical debt share is 13.5 hours, or 33%. The 42% covers everything labeled maintenance, including debugging and modifying code, so the headline figure is higher than the source supports for debt alone.
Tornhill and Borg's own study is more useful because it measured. They analyzed 39 proprietary codebases, 30,737 files in all, matching a code-quality score called Code Health with issue data from Jira over 6 to 12 months. Comparing averages, files in the lowest category had 15 times more reported defects than healthy files, took 124% longer to develop and showed maximum cycle times nine times longer. The same paper adds a figure it takes from a survey by Martini, Besker and Bosch, which I have not opened: it states that as few as 7.2% of organizations methodically track technical debt. That survey's abstract on the Chalmers repository gives 7.2% as the share of its 226 respondents, so I read it as a share of people and not of companies. Tornhill and Borg name one caveat themselves: causation could run the other way, with defect-laden code scoring badly. Another is visible from the paper's front matter: the codebases came from users of CodeScene, the tool that computed the score, and Tornhill's affiliation is CodeScene. One further number matters for allocation: only 350 of the files, 1.14%, were in the lowest category, and 9.87% were in the middle one. I read that as support for the idea that the expensive debt is concentrated, which is what makes a short register plausible. The study does not test that reading.
The Ernst team's 2015 survey of 1,831 participants, mostly engineers and architects at three large organizations, found that architectural decisions were the most important source of debt and that respondents did not find existing tools helpful for managing it. I would expect architectural items like the order module to carry the largest bills and the least tool support. The register's interest column has to come from tickets and version control: take the changes from the last two quarters that touched the item, compare their time in development with comparable changes elsewhere, and multiply the difference by the count. Doing this by hand for five modules should take a few hours, which is my guess and not a measured figure.
A 2026 arXiv preprint by Yue Liu and colleagues, revised in October, looks at AI assistants through the same lens. It tracked about 300,000 AI-authored commits in roughly 6,300 public repositories with static analysis and found 484,366 issues, 89.3% of them code smells, with 22.7% still present in the latest revision. Those counts describe an inventory, and by Fowler's logic an inventory is not interest, since a smell in a file nobody changes costs nothing. My own inference, which the study does not test, is that generating code lowers the price of borrowing, and a cheaper loan gets taken more often. If that holds, a team gains from knowing its rate before AI-assisted volume arrives, since afterwards there is more code to price.
The strongest objection: interest is too uncertain to rank anything
The best case against all of this is that a register manufactures precision. The evidence above supports part of it. Self-reports differ by nearly a factor of three between employers, the survey estimates are self-reported and were not checked against any one codebase's tickets, and Fowler himself concedes that design quality and productivity are hard to measure. An interest column filled with confident decimals can make a guess look like an audit, and teams competing for repayment budget have a reason to inflate their numbers. A manager who trusts the table over the people closest to the code has made a worse decision than one who simply asked them.
I accept the risk, and I see three reasons the register is still worth keeping. First, the made-up portfolio above has paybacks spanning a factor of nine, from 5.3 months to 50, and a rule on payback survived errors of a factor of two. A real portfolio may be tighter, in which case noise matters more, but my guess is that a factor of two is about the accuracy a few hours of ticket analysis can reach. Second, the alternative to an explicit estimate is an implicit one, made by whoever speaks first in the planning meeting, with no record to check against later. A register can be audited, because the extra hours per change are observable after the fact and each quarter's re-pricing will show which estimates were off. Third, gaming has a partial counter: tickets, not opinions, should supply the interest column, and someone outside the team that wants the budget should check it.
The register also has limits that no amount of care removes. It prices interest in hours, and some interest is paid in other currencies. Cunningham's own warning about extreme specialization describes a cost that appears as slow onboarding and dependence on one engineer nobody can replace, neither of which shows up in cycle time. Security shortcuts carry an expected loss and not a steady stream of extra hours. Items also interact, so repaying one can change the interest on several others. A table of independent rows cannot capture that, and none of the sources above offers a method that does.
The first version fits on a page. List the five modules your team changed most last quarter, pull the cycle times for the changes that touched them, subtract the median for comparable changes elsewhere and multiply by the count. What I cannot settle is how to put a number on the interest that is paid in people, and none of the sources I read attempts it.
Sources
- Cunningham, W. (1992). The WyCash Portfolio Management System. OOPSLA '92 Experience Report, dated 26 March 1992. http://c2.com/doc/oopsla92.html
- Cunningham, W. (2009). Debt Metaphor (video, YouTube). I did not watch the video; the essay relies on summaries of the transcript posted by Philip Schwarz, "The Debt Metaphor: Ward Cunningham in his 2009 YouTube video", Speaker Deck, plus the Agile Alliance's quotation of the same passage. https://speakerdeck.com/philipschwarz/the-debt-metaphor-ward-cunningham-in-his-2009-youtube-video
- Fowler, M. (2009). Technical Debt Quadrant. martinfowler.com, 14 October 2009. https://martinfowler.com/bliki/TechnicalDebtQuadrant.html
- Fowler, M. (2003, rewritten 2019). Technical Debt. martinfowler.com. https://martinfowler.com/bliki/TechnicalDebt.html
- Fowler, M. (2007). Design Stamina Hypothesis. martinfowler.com, 20 June 2007. https://martinfowler.com/bliki/DesignStaminaHypothesis.html
- McConnell, S. (2008). Managing Technical Debt. Construx Software best practices white paper, version 1, June 2008. https://www.construx.com/wp-content/uploads/2019/02/CxWhitePaper_TechnicalDebt.pdf
- Besker, T., Martini, A., Bosch, J. (2019). Software developer productivity loss due to technical debt: a replication and extension study examining developers' development work. Journal of Systems and Software 156, 41-61. https://doi.org/10.1016/j.jss.2019.06.004
- Tornhill, A., Borg, M. (2022). Code Red: The Business Impact of Code Quality, a quantitative study of 39 proprietary production codebases. International Conference on Technical Debt (TechDebt) 2022, 11-20, doi 10.1145/3524843.3528091. Figures read from the arXiv version. https://arxiv.org/abs/2203.04374
- Stripe (2018). The Developer Coefficient: Software engineering efficiency and its $3 trillion impact on global GDP, survey by Harris Poll for Stripe, September 2018. https://stripe.com/files/reports/the-developer-coefficient.pdf
- Ernst, N., Bellomo, S., Ozkaya, I., Nord, R., Gorton, I. (2015). Measure it? Manage it? Ignore it? Software practitioners and technical debt. Proceedings of the 10th Joint Meeting on Foundations of Software Engineering (ESEC/FSE), 50-60. https://sei.cmu.edu/library/measure-it-manage-it-ignore-it-software-practitioners-and-technical-debt
- Liu, Y., Widyasari, R., Zhao, Y., Irsan, I. C., Chen, J., Lo, D. (2026). Debt Behind the AI Boom: A Large-Scale Empirical Study of AI-Generated Code in the Wild. arXiv preprint 2603.28592 (submitted March 2026, latest revision October 2026; figures in the text follow the latest version and may change). https://arxiv.org/abs/2603.28592
- Illustrative borrowing example: good path 160 h, quick path 60 h, replacement 160 h plus 20 h ripping out (160 h in the tangled variant), 6 h per month interest, survival after 6 months or abandonment after 3 months, 30% abandonment probability, quick version assumed to ship three weeks earlier. All made up; arithmetic checked with Python.
- Illustrative register, repayment budget and simulation: five items with the principals, change counts, extra hours and lifetimes shown in the table, 200 h budget, a 3% monthly interest growth for the compounding example, and 10,000 draws of an error factor between 0.5 and 2 on each interest figure. The rule funds items whose estimated payback is at most 12 months and shorter than their life, in order of payback, until the budget is spent. Results were stable across four random seeds, and the random-order baseline (about 440 h) is the mean net saving over repeated random orderings of all five items within the same budget. All made up; computed with Python.
- Sculley, D., Holt, G., Golovin, D., Davydov, E., Phillips, T., Ebner, D., Chaudhary, V., Young, M., Crespo, J.-F., Dennison, D. (2015). Hidden Technical Debt in Machine Learning Systems. Advances in Neural Information Processing Systems 28 (NeurIPS 2015). Mentioned for attribution only; no figures are taken from it here.
- Martini, A., Besker, T., Bosch, J. (2018). Technical debt tracking: current state of practice: a survey and multiple case study in 15 large organizations. Science of Computer Programming 163, 42-61, doi 10.1016/j.scico.2018.03.007. Cited through Tornhill and Borg (2022) for the 7.2% figure; I read only the abstract on the Chalmers repository record (https://research.chalmers.se/en/publication/541489), which gives 7.2% as the share of its 226 survey respondents who track technical debt methodically, not a share of organizations.