When you think about the role of debt in running a business, you may think about the monetary cost – interest rates, principal, payment schedules, and fees. However, debt can be more than a monetary cost. In fact, most debt doesn’t have tidy numbers next to it.
When your auto mechanic says, “You’ll pay for that later if you don’t take care of it now,” that’s debt, but its cost may not be obvious. For example, you can leverage that debt to create opportunities—deferring less urgent repairs may allow you to afford a road trip with friends. You can also take on too much or the wrong kind—by not repairing anything, you risk breaking down on the road trip at a considerable cost. When the risk is not always clear, a trustworthy tradesman who understands your needs and can explain which improvements need to happen is worth their weight in gold.
The same is even more true in the world of software development. Technical debt is the result of sacrificing long-term goals for short-term gain. It can be a powerful tool, but it can just as quickly become an anchor that hampers progress. Taking on too much technical debt, doing so at the wrong time, or taking on the wrong kind can leave a project in a precarious position. Those three factors—the type of debt, total debt, and the timing of debt—are at the crux of how we decide when it makes sense to take on more technical debt.
Let’s quickly walk through various aspects of technical debt and when or if it makes sense to leverage them.
The Cost of Technical Debt
As with most other varieties of debt, technical debt requires that you make payments toward both the principal and interest. When developers take time to redesign and rebuild code to apply lessons they’ve learned—which we call refactoring—that’s a payment toward the principal. When developers lose time because they’re working with code that needs to be updated, that’s a payment toward the interest. When too much technical debt accumulates, interest payments can overtake all other work, paralyzing the project.
To provide a concrete example, I once took over a project that involved regular requests to add more data on a particular screen. Experience with their previous developers taught the client to expect a 1-week turnaround on each request. After refactoring the code in about that same amount of time, subsequent requests took less than 5 minutes. By recognizing the technical debt, we paid off the principal once and for all. Instead of those requests costing the client a week every time, they cost the client a week one last time. The frustrating thing is that this example is not an outlier.
How do you know if your project has technical debt? While the list below is not exhaustive, here are some indicators your project is likely to have accumulated technical debt:
- Instead of smooth progress, work proceeds in lurches and fits.
- Simple changes to common elements take longer than expected.
- Technical documentation is outdated or nonexistent.
- The team is spending more time fixing bugs than on new features.
- Bugs are frequently reintroduced when making changes.
- Developers are not conducting code reviews.
- Developers know about bugs in their work but ship it anyway.
- The project has neither automated tests nor a manual QA process.
- The team does not use a system to track and eliminate technical debt.
- Developers talk openly about the project’s technical debt.
- The development team lacks ongoing training and education.
Types of Technical Debt
While many ways exist to describe technical debt, one of the most useful and widely adopted categorizations is Martin Fowler’s Technical Debt Quadrant. In it, he argues that all technical debt falls into one of four quadrants:
- Reckless and Deliberate: Working in a “quick and dirty” fashion without a plan to address problems later.
- Prudent and Deliberate: Taking on debt to accelerate short-term velocity, but with a plan to pay the debt later.
- Reckless and Inadvertent: Naïvely accumulating debt without even realizing it’s happening.
- Prudent and Inadvertent: Engaging in best practices, only to discover later that you now know enough to have done it better.
Inadvertent technical debt is inevitable, but practices such as code reviews, QA testing, and ongoing training limit the degree to which it can catch a team by surprise.
Reckless and Deliberate technical debt sets the project on a course for failure, usually because unreasonable demands receive insufficient pushback.
On the other hand, Prudent and Deliberate technical debt can be an effective tool in hitting a tight deadline, provided you allow for paying down the debt later.
When to Incur Technical Debt
Now that we understand the types of debt, when does it make sense to consider taking on technical debt?
- When the first mover advantage is most important: Being the first to market may be more important than being the best. In that case, cutting corners to get there faster—but with a plan to address those issues later—may be the more prudent course of action.
- When quality doesn’t matter: A proof of concept is designed to be thrown away once it’s served its purpose, at which point its debt disappears with it.
- When the risk of abandoning the work is high: Not every idea is a winner. It’s generally better to get an MVP (Minimum Viable Product) out the door, gather data about what works in the market, then invest in the areas with the most interest.
- When the work needs to be delivered ASAP: If a critical bug is live in the wild, allowing a half-fix that improves the situation is often better than doing nothing.
In each of the above, however, it’s necessary to weigh the technical debt you are considering against the technical debt you already have. Timing is just one factor; you must also consider the type and total amount of debt.
How to Manage Technical Debt
Technical debt is inevitable in software development, but managing it well requires foresight and planning. Here are a few tips to prepare for technical debt in your project:
- Remember to consider the types of debt, total debt, and the timing of debt when deciding whether it makes sense to take on more.
- Limit Inadvertent technical debt by ensuring your team has processes for code reviews, QA testing, and ongoing training.
- To the degree possible, minimize wasted effort when taking on debt. Leaving a gap you’ll need to fill later is fine, but avoid work you know will need to be refactored later by the team. Focus on work that the team can reuse.
- Nearly every project is bespoke in software development, so having both breadth and depth in your team is key to avoiding Inadvertent technical debt.
- Be wary when developers suggest technology for no reason other than that they’re comfortable using it. A hammer is not always the right tool for a job, and blogging software is rarely the right tool for a high-traffic retail site.
- Work with teams that seek a deep understanding of your industry and how your business fits within it. They are more likely to avoid misunderstandings that result in costly refactors later.
- Keep interest payments to a minimum by encouraging developers to refactor code regularly when they can do so at a minimal cost, thus keeping your principal small.