In a software company, people often talk about tech debt, usually blaming it for something bad that is happening, such as
Even though tech debt is mentioned frequently, it is rarely explained in a way that everyone can understand. All too often, misconceptions and misinformation drive the conversation. Tech debt can be a big deal, sinking products or even whole companies when it reaches a tipping point. So it’s important for everyone to gain a better understanding of what it is and how to manage it.
Tech debt is an umbrella term for many types of code issues that have the end result of making a piece of code hard to work with — hard for a dev to read, understand, and make changes to without also creating unpredictable results and unwanted side effects.
Here are some types of tech debt, grouped by severity:
Low Severity
Medium Severity
High Severity
Extreme Severity
As tech debt accumulates, devs become less productive. An organization must move beyond the myths surrounding tech debt, so people can take coordinated action to keep it under control.
Too often, the term ‘the tech debt’ is used, suggesting it is some single big, amorphous cloud of bad stuff which is inevitably growing, sure to swallow the codebase whole in the near future. Characterizing tech debt this way can lead to inaction and hopelessness.
‘The tech debt’ in actuality consists of many discrete problems — similar to bugs, but invisible to end users and primarily impacting dev productivity. Like bugs, tech debt issues can be itemized, sized, prioritized, and incrementally fixed.
Not all tech debt is created equal — problems in frequently-modified mainline code is much more impactful than issues in rarely-touched code.
Quantify tech debt by documenting issues in a spreadsheet or issue tracker. Capture the frequency, impact, cost to fix, and other important prioritization factors. Rank the issues as a team, taking care not to lose sight of the frequently occurring ‘papercut’ issues that affect everyone, adding up to a large amount of lost time overall.
⭐ Create an inventory of specific tech debt issues, prioritizing based on how much each item impacts the team.
People in technology companies have strong opinions about where tech debt comes from. Product Managers might say that tech debt comes from lazy or incompetent devs writing crappy code. Developers might say that rushed projects, focused on time to market above all else, result in insufficient time to write quality code. And so on.
In truth, there are three major causes of tech debt:
1. Intentional tech debt is caused by teams taking shortcuts to deliver prototypes or meet short deadlines. Skipping steps of the engineering process — such as refactoring, automated test coverage, peer review, error handling, and logging — saves time in the short run, but creates tech debt. Similar to a financial loan, the team gains a short-term benefit at the cost of future ‘interest’ payments (in the form of lower productivity) until the debt is repaid.
2. Unintentional tech debt occurs when code is poorly engineered due to inexperience, incompetence, or lack of motivation. In a high-functioning team, these things will be caught through peer review of code and designs; but if a team is skimping on reviews (due to tight deadlines), tech debt can slip in unnoticed. Another source of unintentional tech debt is when code is written against misunderstood requirements.
3. Tech debt caused by the passage of time occurs when incremental enhancements and bug fixes to a piece of code cause a gradual loss of structure; this is sometimes called ‘bit rot.’ It can only be prevented through refactoring, which takes extra time. Also, as customer usage patterns change, old requirements or features may become obsolete, and if their code isn’t removed or refactored, it becomes tech debt.
Tech debt has multiple causes, so it is crucial for the team to be candid about them, take responsibility, and avoid pointing fingers. Unintentional tech debt is the most insidious of all, because it is often avoidable and yields no beneficial side effects.
⭐ Use peer review and mentoring by experienced devs to stop unintentional tech debt during the design and coding phase.
Some engineers say that tech debt is so costly, it should never be created intentionally. This is an incorrect statement, because tech debt is a valuable tool when used correctly — similar to a company borrowing money to make a time-critical investment.
There are three cases where intentional tech debt is justified:
1. Building a prototype or demo. The team is delivering a proof of concept or prototype to gain hands-on feedback of a new product or feature; or an interactive demo to help close a major customer, partner, or funding round. The correct high speed, low cost approach is to cut corners and create code that will be thrown later.
2. Time to market is critical. The new product or feature needs to be expedited for reasons outside of the team’s control. Cutting corners buys valuable time. The code will be improved, not thrown away, in the near future, immediately after the deadline has been met.
3. Requirements are likely to change. Building a new product or feature entails guesswork regarding what customers truly want. If requirements are guaranteed to change, then cutting corners and writing short-lived code reduces the cost of rework.
Creating tech debt intentionally can be a ‘slippery slope’ — teams should proceed with caution!
Teams should discuss the rationale for creating tech debt, and decide whether code will be thrown away or improved in the future. Clearly document the decisions, and communicate to everyone.Ensure everyone on the team is aligned on the strategy. Some may have a negative emotional reaction due to past experiences. The team needs clear boundaries. Review the rules on a recurring basis to keep everyone aligned.Create a schedule that budgets time to fix the tech debt as soon as possible.Avoid high severity tech debt — obscure code, overly complex code, and insufficient test coverage are so toxic that these shortcuts are never worth it, unless the code is going to be thrown away.Update the tech debt inventory (whether it is in a spreadsheet or an issue tracker) with new items on a regular basis. Confirm that the schedule for fixing the tech debt provides sufficient time to address the issues.
⭐ Create new tech debt carefully: align the team on the rules, quantify and document the impacts, and commit to a plan for fixing it in the future.
Tech debt is frequently referenced as primarily a morale issue for devs. This view severely downplays the impact of tech debt on the entire company.
Tech debt affects everyone, in indirect yet profound ways:
The dev team is merely the ‘canary in the coal mine’ of tech debt — if they are unhappy, then it is likely that everyone will be unhappy in the future, unless action is taken.
⭐ Educate all stakeholders about how tech debt impacts them. Be specific about high priority problem areas and the action plan to fix them.
When ignored, tech debt accumulates quickly — with compounding drags on velocity, quality, and morale. When its impact becomes easily visible, the situation can seem dire. Lacking an inventory of specific tech debt items, the organization sees it as a big, amorphous cloud. Before long, the term ‘full rewrite’ is thrown around by devs describing the only way to fix the situation.
This is dangerous territory, because even when this conclusion is unfounded, it can take on a life of its own — becoming a self-fulfilling prophecy:
Devs who believe a ‘full rewrite’ is the only solution adopt a fatalistic perspective that the current codebase is beyond help, which can lead to taking coding shortcuts that make the situation even worse.Meanwhile, stakeholders balk at the huge price tag and risks of a full rewrite. Rewrites are usually fraught with problems, take much longer than expected, and are rushed at the end — leading to brand new tech debt!
In rare cases, a full rewrite is necessary; but more often a detailed plan of incremental fixes is most appropriate, rewriting modules or components, a few at a time. The team must take a rigorous approach, identifying the highest priority items and tackling them first. Automated test coverage is essential, because any side effects or breakages from the cleanup are immediately known.
⭐ Avoid saying ‘full rewrite’ — instead, use the tech debt inventory to identify components/modules to fix each quarter.
To manage tech debt effectively, companies need to move past the myths and misconceptions that get in the way of meaningful discussions about specific issues and how to deal with them.
You can address tech debt in your own company by educating people. Dispel the myths — a great first step is creating an inventory of the worst issues, and building an action plan to fix them.