DEV Community

Cover image for Technical Debt: A Financial Framework
Wolyra
Wolyra

Posted on • Originally published at wolyra.ai

Technical Debt: A Financial Framework

Technical debt gets talked about like a moral failing. “We have so much tech debt.” “The team keeps cutting corners.” “We need to stop and fix things.” The framing is usually emotional, which means the decisions that follow are usually not very good.

A CFO talking about financial debt does not sound like this. A CFO talks about principal, interest rates, covenants, amortization schedules, and the cost of capital. Debt is not good or bad — it is a financial instrument with a specific cost and a specific use. Some debt is smart. Some is ruinous. The analysis is what distinguishes the two.

Technical debt works the same way when you frame it the same way. This article lays out the framework we use with engineering leaders and their finance counterparts. It treats tech debt as debt, with all the terms that implies. It is not a perfect metaphor, but it produces better decisions than the moral framing, and it gives engineering and finance a shared vocabulary.

Principal: what you actually did wrong

The principal of a tech debt is the thing in the system that is structurally wrong. Not the symptom, the structure. The database schema that should have been normalized and was not. The authentication module that was never refactored out of the monolith. The shared utility library that became a dumping ground because nobody defined what it should contain.

Principal has a size. You can estimate the engineering effort to fix it. Some debt has small principal — a day or two of work. Some has enormous principal — a multi-quarter refactor with no product visibility.

The first discipline is naming the principal clearly. Not “the codebase is messy.” That is not a debt, it is a complaint. A debt sounds like “the order service uses three different idempotency strategies because the team never consolidated them after the rewrite.” That is a specific, sized, addressable principal.

Interest: the ongoing cost of leaving it

The interest on a tech debt is the ongoing cost you pay for leaving the principal in place. Interest takes several shapes:

  • Feature velocity tax. Every new feature that touches the debt costs more to build than it should. Engineers work around the debt instead of through it.
  • Incident surface. The debt contributes to outages that would not happen if it were not there.
  • Hiring and onboarding cost. New engineers take longer to become productive because they have to learn the debt before they can contribute.
  • Cognitive load on the team. Engineers working in a codebase with significant debt carry more in their head just to move safely. This shows up as burnout eventually.

A debt with large principal and low interest is not a priority. It is ugly, and fixing it might feel satisfying, but if it is not costing you anything meaningful, other things should go first.

A debt with small principal and high interest is a gift. It costs little to pay off and saves a lot. These are the ones that almost always get ignored because they are not dramatic.

Rate: how fast the cost is growing

Interest rates on tech debt are not static. Some debts compound — they get more expensive over time, often faster than the business grows. Others stay flat. A few actually decrease in relative cost as other parts of the system move around them.

Compounding debts are the dangerous category. Examples include schemas that accumulate more data every day (the cost of migrating them grows with the data), integrations that get more consumers over time (every new consumer is another coordination problem when you fix the root), and abstractions that become load-bearing across more of the codebase (the cost of replacing them grows with the blast radius).

Flat-rate debts can usually wait. Compounding debts cannot. A debt that is doubling its cost every year, even from a small base, will be catastrophic inside five years if not addressed. The rate is as important as the absolute interest.

When to take debt deliberately

Taking debt is not always wrong. Sometimes it is the right business decision. The legitimate reasons to take tech debt on purpose:

Time-to-market. Shipping a product four weeks earlier can be worth significant future refactoring cost, especially when the market window is real. The honest analysis is: how much principal are we taking on, how much interest will it cost per quarter, and when do we pay it down? A plan that ends with “we will clean it up later” without a specific trigger is not a plan. It is a wish.

Option preservation. Sometimes you do not know enough to build the right abstraction yet. Taking some duplication in the short term, with an explicit note that it will be consolidated when the shape is clearer, is a legitimate trade. Premature abstraction is its own debt.

Low-cost-to-exit code. Code that is clearly experimental, whose blast radius is small, and whose removal is known-cheap, can be shipped with less rigor than production-grade code. The constraint is that the “throw it away” path has to be real and planned, not a story the team tells themselves.

When to refuse debt

Some categories of debt should not be taken, even for time-to-market. These are the debts whose interest is disproportionately high or whose principal grows catastrophically.

  • Safety-critical paths. Any code in the path of security, privacy, or data integrity should not carry deliberate debt. The interest on these debts tends to manifest as breaches, not as slower velocity.
  • Compliance-relevant code. Audit trails, access controls, and regulatory logic. Taking debt here creates regulatory exposure that is not easily quantified in engineering terms.
  • Core data models in a system with external consumers. Once other systems depend on a shape, changing the shape is not a refactor. It is a coordinated migration across organizational boundaries. Start correctly.
  • The build-vs-buy choice itself. Taking a wrong build-vs-buy decision deliberately, with a plan to revisit it later, is almost always worse than it looks. The cost of reversing is higher than the cost of getting it right up front.

How to pay down

Two patterns for paying down debt, each appropriate in different situations.

Dedicated capacity

A percentage of engineering time, explicitly protected, dedicated to reducing principal on debts the team has agreed matter. Something like fifteen to twenty percent of capacity is common and sustainable. This approach works for debts that require sustained attention — refactoring a module, untangling a dependency, rewriting an integration layer.

The failure mode of dedicated capacity is that it gets reallocated the moment a deadline slips. Once that happens twice, the team stops believing in it, and the protected time effectively disappears. The only way dedicated capacity works is if leadership holds the line on it even when a quarter is under pressure.

Opportunistic repayment

When an engineer is working in an area of the codebase for a feature, they fix the small adjacent debt they find. This works well for low-principal, high-interest debts that are scattered throughout the codebase. It does not work for anything that requires coordinated attention across multiple services or teams.

The failure mode of opportunistic repayment is that it creates inconsistent quality across the codebase. Areas that get frequent features get progressively cleaner. Areas that get ignored accumulate debt that never gets addressed until it causes an incident. A healthy program uses both patterns together.

The quarterly debt review

The practice that makes all of this real is a quarterly review. Not a conversation — a scheduled review with a specific format. The team maintains a list of known debts, and every quarter the list gets reviewed against four questions.

  1. Principal size: how big is the fix, honestly estimated?
  2. Current interest: what is this costing us per quarter right now?
  3. Rate: is the interest stable, growing, or shrinking?
  4. Business relevance: does the area this debt lives in still matter to the product direction?

From that review, the team picks a small number of debts to pay down in the next quarter. Not everything. A small number. The rest stay on the list, tracked, aging.

Debts that have been on the list for several quarters without being addressed are a signal. Either they are not actually causing the cost you thought they were (in which case remove them from the list honestly), or the organization has a prioritization problem (in which case the review itself is revealing something).

The mistake finance understands and engineering sometimes does not

The biggest mistake in tech debt management is the same as the biggest mistake in financial debt management: taking on new debt faster than you are paying down the old.

Every sprint adds a little new debt somewhere. That is normal. A healthy system pays down at least as much debt as it takes on. An unhealthy system takes on more than it pays down, quarter after quarter, and the compounding interest eventually becomes the dominant cost of engineering.

The signal that this has happened: engineering velocity has been dropping quarter over quarter, and the team cannot point to a specific reason. That is the debt working in the background. At that point, no amount of hiring fixes it. The only answer is a deliberate, measured program to reverse the direction.

Tech debt is not a moral issue. It is a financial one. Treat it with the same rigor the rest of the business treats leverage, and the decisions get much clearer.

Top comments (0)