Technical debt is part of pretty much every one of our development engagements. It’s the starting place for some projects — a client comes to us when their technical debt has gotten too big to manage — but even when we’re building something from scratch, technical debt is a reality we’ll contend with in some way or another. Let’s be honest: we’re all carrying at least some technical debt.
It’s not always a bad thing to carry some technical debt, but like actual money debt, it can be intimidating to talk about and easy to avoid until it avalanches and is too big to ignore. We prefer to be honest and up-front about what you have, and any you’re considering taking on.
Let’s start with the basics: What is technical debt and where does it come from?
What is technical debt?
The term “technical debt” originated from a conversation that engineer Ward Cunningham had with his CEO. He was trying to explain the tradeoffs of a development decision, and compared it to a growing business: do you take out a loan to go faster, or slow down and pay cash as you go? Borrowing isn’t bad, he explained, it’s just not free. You have to pay interest.
Technical debt includes any tasks you choose not to do now, but will continue to cause future problems until they are completed.
It also includes any and all the pre-existing debt you’re carrying. When you have amassed a lot of technical debt, it can feel like the wings coming off. It often sounds like this: We can’t refactor the thing because of this other thing, and also this other thing? No one knows anything about it, how it got there, how it works, or if there’s any documentation. So… we have to rebuild the plane while flying it?
We’ve (unfortunately) been there. Let’s learn why.
THE 13 TYPES OF TECHNICAL DEBT
Just like how financial debt comes in a few flavors — student loan, credit card, medical bills, mortgage — there’s a bunch of types of technical debt. In 2014, a group of academics created categories for every type of technical debt that exists. They found 13.
- Architecture debt: Problems in project architecture that impact performance and robustness. An example is violation of modularity, or when two modules that should evolve separately are inappropriately linked. Unfortunately, this kind of debt is typically not a quick fix and requires extensive development.
- Build debt: Any build issues that make the task harder or more time-consuming, including unnecessary code or ill-defined dependencies.
- Code debt: Problems in the source code that affect its legibility. These can be pretty easy to spot simply by looking at the code to see if there are any bad coding practices.
- Defect debt: Known defects like user-reported bugs that everyone agrees should be fixed, but aren’t due to competing priorities or resource limitations. This debt often comes with compounding interest, since delaying defect fixes can make them harder to fix later on.
- Design debt: Code that demonstrates bad design practices, like very large or tightly coupled classes.
- Documentation debt: Missing, inadequate, or incomplete documentation. This is incredibly common, since it’s hard to prioritize documentation when you’re building quickly.
- Infrastructure debt: Issues like delayed upgrades or infrastructure fixes that can delay development.
- People debt: Any kind of people issues that can delay or hinder development, including training or hiring needs, or having expertise concentrated in too few people.
- Process debt: These are inefficient processes, like the ones that were built to handle one load and no longer work well for the current load.
- Requirement debt: Tradeoffs that the dev team has made, including partially implemented requirements, or an implemented element that fits the security needs but not the performance needs.
- Service debt: When business or technical needs require a web service substitution, there’s technical debt in choosing and operating that service. That is, the switching cost incurred when you migrate from Amazon Web Services to Google Cloud Platform, or vice versa.
- Test automation debt: The work involved in automating existing tests so they can be integrated into a faster development cycle.
- Test debt: Issues found in existing tests that affect their quality, like planned tests that weren’t run, or low code coverage in the test suite.
The technical debt quadrant
It’s easy to think that technical debt is just coding malpractice, but that’s not at all the case. Technical debt isn’t always due to incompetence or maliciousness — some of it’s purposeful and even prudent. Martin Fowler’s quadrant of technical debt explains it perfectly.
On one axis, the technical debt can be prudent (you can afford to take it on) or reckless (you can’t). To use the consumer debt analogy, prudent debt might be taking on a mortgage at a price-point you can afford to pay; reckless debt is swiping the credit card and crossing your fingers it won’t be declined.
On the other axis, the debt has either been thoughtfully considered and accepted (deliberate), or it was simply incurred and you’re surprised to find out (inadvertent). In the consumer debt analogy, one is like knowingly taking out a loan, the other is getting a surprise bill in the mail.
When you put them on the quadrant, there are four ways technical debt is incurred:
- Reckless and deliberate: When you’re aware of the risk (and it’s a big one) then take it anyway. It might sound like: “We don’t have time for testing!”
- Reckless and inadvertent: When you don’t know what you don’t know — and why working with experienced developers is one of the best ways to mitigate it. It might sound like: “What’s authentication?”
- Prudent and deliberate: When you determine the risk is worth it. It might sound like: “We’ve gotta ship this now and accept the consequences.”
- Prudent and inadvertent: When you learn more by doing the project, so by the end you’re aware of technical debt. We’ve all been there: you’ll learn something in doing the project that you wish you knew from the get-go. It doesn’t mean the project is bad or a failure — it just means you’ll do it differently next time. It might sound like: “That’s how we should have done it.”
Our POV: It’s key to be comfortable talking about technical debt
We’re actually uncomfortable not talking about it. That’s because most existing projects have some technical debt, and every project we embark on has the potential to incur it. This is crucial information as we map out a project plan and prioritize our work.
Stay tuned. Next up in the technical debt series: When to take on technical debt, and when to pay it off.