What is Technical Debt? Examples, Prevention & Best Practices

technical debt

Most software developers are familiar with technical debt, but that’s less true for those outside the programming profession. The concept is important to understand, however, because it applies not just to programming but also to a wide range of scenarios where short-term decisions can have long-term consequences. Here’s what you need to know.

What is technical debt?

Simply stated, technical debt is created when software development teams put speedy delivery ahead of optimal code quality. This is often intentional. The user may need functionality in a hurry, and so developers elect to deploy code that’s “good enough,” intending to fix it later. The debt metaphor is appropriate. When one assumes a debt, it’s often because financial resources are needed on a short-term basis. However, this creates additional costs down the line when that debt must be repaid.

Technical debt works in a similar way, trading expediency for additional work down the line. If the code isn’t eventually revisited and fixed, it can become a problem, just as interest and penalties can accrue if loan payments aren’t made. Technical debt is not necessarily a problem, but it can become one if the product is poorly optimized or if dysfunctional code is allowed to proliferate.

The risk of creating technical debt can be amplified by a shift toward agile development techniques. DevOps encourages frequent code releases and constant enhancement, and developers who are under pressure to push out new code every day or every few hours may shortcut documentation rules or testing.

Examples of technical debt

A classic example of technical debt is the Year 2000 problem. Many software developers in the 1960s and 1970s chose to save precious memory by storing dates as two digits: “73” instead of “1973.” The practice continued for years, even as memory prices declined. Many of those programs became embedded into the operational business and stayed in use far longer than anyone had expected. As the year 2000 approached, thousands of businesses and government agencies realized that date calculations would fail at a massive scale and so undertook a frenzied clean-up effort. Addressing the Y2K problem is estimated to have cost $100 billion.

Technical debt isn’t limited to software, though. For example, a best practice in cybersecurity is to grant file permissions to roles within the organization rather than to individuals. Suppose an administrative assistant gets approval from his boss to gain temporary access to sensitive documents that he wouldn’t ordinarily be authorized to see. If the IT organization grants the exception and fails to revoke it later, it has granted permanent access to sensitive documents to an account that could eventually become compromised and present a vulnerability.

What are the downfalls of technical debt?

If short-term fixes are refactored quickly and developers know how to handle technical debt, there is little downside to accruing technical debt. There may even be benefits, as it can enable a business to respond quickly to opportunities or problems.

The risk grows when debts are layered on top of each other. Quick fixes may be poorly documented or not documented at all, and when the people who performed the quick fixes leave, the company may have no one who knows how the code is supposed to work—or even that the quick fixes exist. Enhancements or changes can create unintended conflicts that cause programs to fail or run slowly. Innovation slows as organizations fail to make improvements out of fear that change will break the application.

What types of technical debt are there?

The two major categories of technical debt are intentional and unintentional. Steve McConnell, CEO of the developer training firm Construx, defines intentional technical debt as that which is taken on consciously and strategically. He defines unintentional technical debt as “the non-strategic result of doing a poor job.”

In 2014, a group of academics developed a taxonomy of technical debt that comprises 13 distinct types, including architecture debt, code debt, defect debt, design debt, process debt, and test debt. This classification is useful because it covers all areas in which short-term thinking can create long-term problems.

How does technical debt happen?

Intentional technical debt is a conscious decision that should be documented and scheduled for refactoring. For example: A regional sales manager is under deadline to generate a report that his platform cannot produce, so he applies an open-source report writer to make his deadline. That’s technical debt. But if the development team allocates resources to remove the open-source report writer and modify the master reporting system to deliver regional results before the business becomes too dependent on the quick fix, it is intentional technical debt.

Unintentional technical debt occurs when changes or additions are made out of expediency and without deliberate plans to refactor the code. It can also be a result of poor design decisions caused by a lack of knowledge or failure to adhere to development standards. Unintentional technical debt in the realm of testing, for example, occurs when test suites are incomplete, or testing is truncated or skipped for the sake of convenience.

Documentation debt is common and happens when developers are too rushed to document their code thoroughly. This can become a big problem in the long term if a person leaves their company and fails to leave a trail that others can use to understand their code. Documentation debt was a major contributor to the Y2K problem.

Infrastructure debt occurs when applications are built to rely upon certain infrastructure components such as databases and file systems. If such dependencies aren’t documented and the company migrates to a new infrastructure, the application may not work.

What are the signs of technical debt?

The warning signs of technical debt are:

  • projects getting bogged down because developers lack insight into the codebase.
  • bugs popping up that are difficult to fix due to complexity or lack of documentation.
  • bug fixes that create new bugs or steady performance degradation

How to manage and prevent technical debt

Knowing how to handle technical debt starts with sound development practices. In a DevOps environment, that includes both shift-left and shift-right testing. Shift-left testing moves the testing process earlier in and throughout the development cycle so that problems can be anticipated and solved before they become embedded in production. Shift-right testing seeks feedback after applications have moved into production so that bugs can be detected early and fixed before the software is in widespread use. These create guardrails that prevent problems from growing out of proportion.

The workarounds that create technical debt are unavoidable and often necessary. It’s important, however, that developers document them, including the reasons why hacks were put in place and instructions for fixing them. Regular audits of existing code can also allow team members to review each other’s work and spot documentation gaps or irregularities.

Why is all of this important?

It’s been said that every company is now a software company. Even businesses in heavy industries are seeking to mine data so that their customers can derive more value from the products they buy. More software is being built each year than has been created in the history of computing, and the trend is accelerating.

At the same time, development organizations are under more pressure than ever to move projects quickly into production. It’s natural for harried developers to cut corners, and project managers should understand and reinforce to their teams that testing and documentation are not throwaway items.

What are the best practices?

As organizations adopt DevOps techniques, they should clarify what is technical debt and apply agile tactics to manage it. This may include implementing shift-right and shift-left testing as well as A/B and canary testing techniques to spot problems before they get out of hand. Peer code reviews allow fresh eyes to examine developers’ work. Developers should work with a consistent and limited set of tools and languages and have a checklist of tasks that need to be completed at each stage. An effective DevOps organization gives developers a lot of freedom to choose how they build their creations but also provides guardrails to ensure they don’t spin out of control.

What tools can companies use to prevent technical debt?

The practices outlined above are a good start. Additional benefits can be realized by using automated testing to run multiple debugging cycles on every code change every time a module change is done. Establishing sound code structure procedures, including mandatory documentation, protects against workarounds. Having programmers work in teams of two can enable them to understand each other’s decisions. Project management tools can enable everyone on the team to see the status of everyone’s work.

An increasing volume of software is being written with low-code and no-code tools. These are, to a great extent, self-documenting, as flowcharts and drag-and-drop techniques enable a visual representation of logic and desired outcomes to be presented.

By applying these tools to professional software development, organizations can benefit from those self-documenting features. Low-code/no-code essentially replaces program and data flow diagrams that development teams already use. Generated code can be run as-is or modified for customization or performance purposes. Development managers should encourage their teams to see low-code/no-code as a productivity enhancement, rather than a replacement for their elegant creations.