“Technical debt” is a term used in software development to describe delayed maintenance costs caused by initial tradeoffs between quality and speed.
It’s a common metaphor on engineering teams as it makes the sometimes opaque costs of technical decisions easy to understand across the team. Technical debt functions just like any other type of debt: convenience now, payments plus interest later.
Thanks to the ever-changing nature of software development tools and standards, every software product will require maintenance and re-building of components over time.
However, the term technical debt is used specifically to describe maintenance issues caused by:
- Deadline limitations
- Budget limitations
- Poor development choices
- Poor development ability
- Inadequate business management
Is Technical Debt Always Bad?
To be clear, technical debt isn’t always bad; it’s a part of every software development project since tradeoffs between speed, cost, and quality are impossible to avoid. Technical debt mainly becomes an issue when it’s ignored by business managers, or accrued unintentionally through poor engineering decisions.
Technical Debt Impacts Business Owners, Engineers, and Sales
The concept of technical debt is helpful for planning the evolution and management of software over time because it acknowledges that cutting corners in the near term will usually generate costs in the mid-long term.
Good management of technical debt makes the difference between success and failure for software projects, by ensuring that a product is manageable and can evolve efficiently over time.
With that in mind, it’s a critical concept for business owners and managers as well as developers, since ignoring it results in higher costs and lower rewards for the business, and increases hours in the chair for development teams.
Sales team members can also benefit from understanding technical debt, especially if selling development solutions to experienced buyers.
Thoroughly understanding technical debt will make you a stronger tech professional by enabling more informed decisions and successful projects.
Solutions To Technical Debt
- High Code Quality: skilled technical contributors and rigorous business processes are table stakes for low-debt software products. Technical debt is common for companies with no high-level technical management or CTO.
- Strong Architecture: high-level decisions about how to build a software product should be made by qualified stakeholders who understand the tradeoffs.
- Quality Assurance: the process of auditing code for issues, both before release and on a recurring schedule afterward. The code that powers software is called a “codebase.”
- Refactoring: the process of regularly re-writing components in a software project, to remove redundancies and optimize performance.
Roadmapping: the process of carefully planning and testing, both prior to investing in a build, and on an ongoing basis throughout the product life cycle. Continuous roadmapping ensures that teams are aligned and that what’s being built is not subjective.
Simple Examples of Technical Debt
To explain the topic, I’ll start with simple examples and build up to more complex real-world cost-benefit analyses, so you can apply the concept in your day-to-day.
Example 1: Deliberate Technical Debt
|Inflexible framework||Team chooses framework that is fast to build on, with known performance and flexibility issues.||Refactor app to more flexible framework after business goal (early launch) is achieved.||Team achieves an early launch, but must re-invest in rebuilds later. Higher overall project cost.|
It’s common for teams to accrue technical debt by choosing to build an app on a framework that decreases development time and costs but is known to break down above a certain number of users.
This technical debt must be paid later by refactoring components to remove low-quality code. However, in this case, it was necessary to reach the market quickly for a first movers advantage.
So long as management understands the costs associated with re-building the product for scaling users after the launch period, this was an acceptable technical debt to take on.
However, there is a risk that management might avoid approving the updates since it’s hard for non-technical managers to see until user-facing app components start to break.
Example 2: Inadvertent Technical Debt
|Low code quality.||Team has low-experience that are developers cutting corners to meet timelines.||Bring on more experienced developers or technical management, ensure code reviews and best practices are adhered to.||Product is shipped with bugs that run up server costs and increase churn.|
Technical debt can also be accrued inadvertently. For example, it’s common for teams to drop their internal best practices and review standards when under a tight timeline. This can lead to code quality issues that a team will not be aware of until they see issues in the product.
In this example, the team didn’t realize they were making trade-offs because they were simply moving as fast as they could. They later discover their technical debt when their competitors achieve a more usable product that accrues more users and eventually locks them out of the market.
This type of debt is also common when teams choose tools they know well or like, rather than the tools which will do the job best, for example using WordPress to run a high-volume eCommerce site rather than a tool made for the job such as Magento.
Inadvertent technical debt doesn’t have to be completely bad. For example, some development studies describe such mistakes as “inadvertent prudent” debt, resulting in “now we know what we should have done” moments that can help develop team skills.
Inadvertent technical debt can often be mitigated by hiring more competent engineers, bringing on experienced technical leadership and management, or by bringing on outsourced DevOps support or development staff augmentation.
Where Technical Debt Comes From
To summarize, there are a variety of ways to generate technical debt:
- Financial limitations
- Putting a team under unreasonable time pressure
- Low-quality developer decisions
- Underqualified development teams
- Low-quality platform or business decisions
- Lack of ownership causing fragmented decision-making
Impact of Technical Debt on Software Project Outcomes
Technical debt can be deliberate or inadvertent — in either case, it has consequences.
The best way to understand the impact of technical debt over time is through visuals:
For the sake of illustration, let’s assume:
- We have an objective way to measure code quality.
- We are delivering the same number of features or changes over time.
With everything else fixed, there are many ways to build. Quality naturally goes down, because applications become more complex, and new features are built on top of increasingly complex platforms.
The gap between the “ideal” quality and real quality is the Technical Debt.
Curves 1, 2, and 3, are trends. The more qualified, the better process, and the better you manage your project, it’ll tend towards (1), (2), or (3). Essentially, technical debt will act as a weight that drags your quality down over time.
Let’s talk about our best scenario (1). The real-life way to achieve it, is through an excellent team, with great practices, and regularly taking the time to pay the debt. One of the most effective ways to pay a debt is by investing in refactors, which means that we’ll rewrite or re-structure already existing (and working) code, to create a higher-quality version of it.
The most important thing to know about technical debt is that it’s not an abstract concept that your developer has to deal with. It affects the creation of value.
If you don’t do anything about it, and your technical debt goes unmanaged, this is what will happen with your project. You’ll see that everything will start to take longer. You’ll see increasingly more bugs. You’ll find that your team will fix one thing and break three.
For a lot of companies, this is the end of the line, because they can’t afford to pay all the compound interest generated by technical debt.
Compounding Impacts of Technical Debt
We can think that the cost of developing a feature is the inherent cost of that feature (under an ideal quality baseline) PLUS the cost of existing debt interest.
It means that you are dealing with a less-than-ideal foundation and it takes time to do something without breaking (or trying not to break) things. It takes time to understand what is done, and why. It takes time to navigate the mess.
New features always create new debt (big or small) and it increases your overall debt.
The bigger your overall debt is, the higher its interest, and more debt is created every single time something is done. Do you see it? It’s an evil self-propelling cycle.
How To Manage Technical Debt
There are two main ways to keep technical debt under control:
- Minimize creation of debt in the first place
- Paying existing debt in an efficient manner
How To Minimize New Content Debt
The less skilled your team is, the more debt is generated. The more you are pressured by time, the more debt is generated. The less your team “loves” your project, the more debt is generated. The more debt you have, the more debt you generate through interest rates.
“Love” can be a strange word here, but it’s related to the broken window theory.
James Q. Wilson and George Kelling 1982 used broken windows as a metaphor for disorder within neighborhoods. Their theory links disorder and incivility within a community to subsequent occurrences of serious crime. The same concept can be applied to a software product.
Developers hate to work on top of low-quality work, and they have a tendency to perpetuate these problems because they are not given the time, or recognition if they improve something that initially is not visible.
On the other hand, they usually love to keep things high-quality, if they have the skills and time to do so. If they love how a product is built, it’s more likely for them to make their best effort to keep quality high.
In a nutshell, with a high-debt project, development takes longer. This increases time pressure on teams and generates more debt. If more team members are added, it also increases entropy (inherent disorder) and generates more debt.
A high-debt project also demotivates developers (less love), generating more debt. It also generates more bugs, which creates more conflicts (questioning quality of work), which reduces how much developers care about the project (less love).
How To Pay Off Existing Content Debt
To summarize, paying off technical debt requires three practices:
- Rigorous QA and automated test development
- A strict refactoring schedule
- Hiring and retaining competent team members or development vendors
- Avoid hiring cheap or low-quality developers
The point of avoiding low-quality developers is very important.
Low-quality developers will create more debt even as they’re working to solve existing bugs and problems with a product. As a result, they cost much more over time — before you even factor in the lost revenue from delivering a less performant, competitive product.
I can’t count how many “rescue mission” projects we had because our clients thought that deciding based on price instead of value was smart. More than 70% of the time our assessment is that even after 1 or 2 years with a non-skilled team, the best option is just “build from scratch”.
And sometimes it only takes a few weeks. Don’t focus on hourly rates, total project cost, or timelines. In fact, my recommendation is not to compare estimations, but to compare the estimation process.
Analyze the process and communication provided by the team when analyzing the project. Focus on building a trustworthy relationship and surround yourself with high achievers.
Final Note: Test, Test, and Test Again
The point on automated testing is also important and often skipped over.
Every programming language has something called “linters” that ensures some standards and enforces a coding style. Check 3rd party tools that assess code quality (like CodeClimate).
When hiring or evaluating progress, Ask what tools your team uses for testing. Ask about their code review process. Ask how they collaborate and aggregate knowledge.
If you can’t afford a highly qualified team, consider not doing the project. A middle-ground option could be hiring a few hours of a highly qualified individual to monitor code quality and processes.
Don’t recognize your team for what you see. It’s very easy to have short-term wins but their long-term work involves much more.
Respect the times they estimate, and recognize that they’ll usually be wrong. The more you pressure your team, the more debt they’ll generate to please you in the short term.
Takeaways For Managers & Business Owners:
- Don’t evaluate projects based on just the parts you see. Make sure there’s a technical team member evaluating the codebase and engineering practices.
- Hire smaller, more experienced teams; not large, cheap teams.
- Build timelines around estimates, not the other way around
- Reward your team based on their technical evaluations, not on how busy they look or how you feel about superficial aspects of the final product.
Takeaways For Engineers & Developers:
- Make sure management is aware of and properly values QA, automated testing, and refactoring.
- Communicate proactively with non-technical team members. If you don’t tell them what you’re doing, they might not know you’re doing it at all.
- Focus on cost when presenting issues to sales or management; they need numbers to justify changing timelines or budgets.
Technical debt isn’t always bad. In fact, it’s a part of every software development project, since tradeoffs between speed, cost, and quality are impossible to avoid. Technical debt mainly becomes an issue when it’s ignored by business managers, or accrued unintentionally through poor engineering decisions.
Technical debt can be broadly split into two types. First, there’s unintended technical debt, which is taken on accidentally, such as by choosing a poor platform or making coding errors. Secondly, there is intended technical debt, such as when a business and engineering manager agree that it is worth sacrificing quality and paying for refactors and code improvements at a later date for the sake of launching more quickly to participate in a competition, or beat a competitor to market.
Technical debt can be avoided by adhering to strong software development processes and standards, such as:
● Rigorous QA and automated test development.
● A strict refactoring schedule.
● Hiring and retaining competent team members or development vendors.
● Avoid hiring cheap or low-quality developers.