Technical Debt

Your team has been working on a codebase. Every few months, there would be a new feature. And the new feature had a timeline of two weeks to deliver. It’s been fun to crunch through and send it to production right before the deadline. But after 3 years, it’s been getting harder and harder to add something new.

That’s Technical Debt.

Technical Debt

This metaphor was coined by Ward Cunningham, in the early 90s, to explain production time to non-technical folks.

Technical Debt is the accumulation of sub-optimal decisions when working in a codebase. They’re not bugs. The code works and the team made the business decision to cut corners to meet the deadline. But over months/years, those corners you’ve cut are fighting back and now it takes even longer to add a new feature.

To use an example:

Let’s say you have a strict deadline to build functionality, so you make the inform decision to shortcut the process. It’s not clean code, but it works and everyone is happy.

If you go back and refactor it, then you’re paying off the technical debt.

But let’s say you don’t fix it. You have 20 other tasks and refactoring wasn’t THAT urgent for you to fix.

Later down the line have another task to add onto that function, and you have to do a funky workaround. Then a few weeks later, you have another funky workaround for THAT workaround. These additional costs are piling up.

As you add more to it, it becomes harder to fix the original sub-optimal code. There’s a lot of functionalities that were tightly coupled together, that fixing it requires you to run up the tree and fix a bunch of other things.

Two years down the line, it really rears its ugly head, and you go, “I wish I fixed it when I first started.” That’s technical debt.

It’s sort of a thing people discover on the job, as their codebase grows. It becomes a problem as new features want to be added, and it’s getting more and more complex to do so.

This metaphor isn’t perfect. Something to address:

Technical Debt is NOT like Financial debt.

  • It’s not like you own somebody money. There’s a lot of use-cases where it’s better to ignore the technical debt than repay it.
  • Technical debt is neither good or bad.
    • Writing a sub-optimal code that works means you can deliver a product faster. The trade-off is that in the future, new additions become harder and harder to implement.
    • The other trade-off is that if the goals of the project changes or the product fail, you wasted a lot of time.
  • Technical debt is done with a purpose.
    • Shaun McCormick’s suggests that true technical debt is always intentional and not accidental. “I view technical debt as any code that decreases agility as the project matures. Note how I didn’t say bad code (as that is often subjective) or broken code.”

What are the reasons to incur Technical debt?

Technical debt can be a business decision.

If you have strict deadlines like you want to be first to market, or need to validate the software’s specs to a client, then faster is better.

Example 1 – Slack:

Slack was a last-ditch product of a game studio on the verge of bankruptcy. Slack was built sub-optimally. To fight off competitors, they focused on more functionality rather than paying off their technical debt and made the business decision to fix it all later.

Example 2 – Using web development:

Your client wants a new website but only has a small budget, you can afford the technical debt and write sub-optimal code to deliver it to them quickly. Since web technology moves quickly, when it’s time to update their site, the client will want a new website anyways.

Example 3 – Visionaries:

If the client doesn’t know what they want until they see it, it’s even more important to work sub-optimally to deliver and validate.

Seeing technical debt from a non-developer

Unless you’re part of the development team, you can’t really see technical debt. If the software works – it works. But using technical debt helps explain it to non-technical folk about the trade-offs of delivering quick results vs delivering clean code.

When it reaches a breaking point, things can get really expensive.

When Slack matured and became a household name, adding new features became harder and harder. They needed to solve their technical debt. The Slack Engineers broke up their main product into various systems, and optimized it one piece at a time, fixing the technical debt and allowing them to add new features in the process.

But sometimes, it’s seen in other ways, like through undiscovered bugs. To ship software faster, Boeing hired engineers at $9 an hour, saving a lot of money but opening up a lot of technical debt, but also lots of other issues. Unfortunately, one of those issues cost $4.9 billion dollars.

Working fast can also cause some other issues.

The U.S. Air Force has decided to scrap a major ERP (enterprise resource planning) software project after spending US$1 billion, concluding that finishing it would cost far too much more money for too little gain.

The original goal was for hired engineers to replace other sub-optimal code, but the technical debt was far too high that not even $1 billion dollars could have solved it.

Types of debt

Not all debt is the result of sub-optimal code. There are a few other reasons for technical debt.

Unavoidable debt – unpredictable/unpreventable.

It can be things like legal issues or making a higher-up decision based on industry trends that didn’t last. For example, it may have been a great idea to write a program with 200,000 lines in Clojure in a decade ago. But now that it’s hard to find devs who work in Clojure… maybe split the 200,000 code system into several systems. That way, you can get rid of it.

Strategic debt – long term debt but short-term gains.

  • You may want to validate an idea or “want to be first in the market”
  • You may also have shifting priorities, so you implement the hack, and will fix it later.

Incremental debt – lots of small shortcuts to meet a deadline.

  • Good idea to avoid over-engineering, and ensure that your development is going in the right direction.
  • Or maybe the code is devolving into unnecessary complexity because it’s worked on by several people who don’t fully understand the original design or the stakeholders don’t know what they really want.

How do you fix Technical Debt

1) Scheduling refactoring into the project plans

Following the Red-Green-Refactor method of Agile – build something that works and then optimize it later. If your project stops at the green, then you’re incurring debt.

2) Share knowledge of what happened

Identifying where things are un-optimized in your codebase. When it’s time to refactor, you might stumble on a better way to do it.

3) Debt conversion

Replace the current solution with a ‘better but not perfect’ solution. Using Javascript as an example – an implementation from ECMAScript 2015 can be improved with newer features from ECMAScript 2019.

4) Defining the clear definition of done

Not all technical debt needs to be resolved. If it’s an end-of-life software/retiring, it’s okay. Going back to the website example – if the project is done when it’s fully functional, and in a few years, it’ll be rebuilt, you can accept the technical debt. Refactoring can be more expensive than working with un-optimized code.


With a clear understanding of Technical Debt, you can make better trade-offs and business decisions.

Leave a Comment