Technical Debt Prioritization Framework
Maintaining technical debt can be challenging when prioritizing and dedicating time to it. This is the first part of a practical guide for creating a workflow to determine and manage technical debt.
TL; TR:
Prioritizing Technical Debt Criteria
Values:
Code Knowledge. How are you familiar with the code?
Severity. How it affects the software's functionality or performance?
Dependency and Scale. How many components depend on that part of the code? The scale of impacted software architecture.
Effort:
Cost of Fixing. How many story points would it cost to fix the technical debt issue?
Use a Ducalis Template.
Integrate into your sprint planning routine.
Log every found technical debt issue into your task tracker.
Use auto-scan apps to detect invisible issues.
Sync tech debt issues from task-tracker to Ducalis for prioritization.
Use score expiration for re-evaluating technical debt regularly.
Create an aggregated Ducalis board with different backlogs: tech debt, features, customer requests, and bugs for an end-to-end prioritized list.
Balance priority scores for all boards to get different issues within one prioritized list.
What is technical debt?
Technical debt is a metaphorical term used in software development to describe the extra development work that arises when code that is easy to implement in the short run is chosen over more robust or scalable options that may take longer. It refers to the cost of taking shortcuts or writing code not optimized for long-term maintainability, extensibility, or reliability.
Examples of technical debt include writing spaghetti code that is difficult to read and understand, using outdated libraries or frameworks no longer supported, failing to document code or tests, and neglecting to perform regular maintenance or updates.
Examples of Technical Debt
Typical Technical Debt Issues:
Using outdated or deprecated technology: Using old or unsupported technology can result in compatibility issues and security vulnerabilities.
Poor code quality: Code that is difficult to read, understand, and maintain can result in bugs, decreased productivity, and increased development time.
Lack of documentation: Failing to document code, processes, and requirements can make it difficult for future developers to understand the software, leading to increased development time and higher costs.
Insufficient testing: Skipping or delaying testing can result in undetected bugs, security vulnerabilities, and user dissatisfaction.
Architecture design flaws: Designing software with a suboptimal architecture or failing to plan for scalability can lead to technical debt as the software becomes more complex and challenging to maintain over time.
Examples of what is NOT considered technical debt:
Deliberately deferring work that is not critical to the project or that can be completed later.
We make informed decisions to take a shortcut to meet a deadline or deliver a prototype quickly.
It intentionally chooses to implement a less-than-optimal solution that is still acceptable for the project goals.
We decide to use a specific technology or tool even though its potential limitations are based on trade-offs with other factors such as time, cost, and business requirements.
We are performing routine maintenance tasks that do not significantly improve the software.
The tech debt problem
The main problem with technical debt is that it can accumulate over time, making adding new features, fixing bugs, or maintaining the codebase harder.
Features take longer to develop
More Bugs
It’s always a trade between improving your code and adding new features.
Technical Debt Prioritization Criteria
Considering these criteria, you can create a prioritization system that helps you identify and address technical debt in your task tracker issues to maximize business value and minimize risk.
Feel free to add, modify or rewrite the criteria name and description for better understanding by your team.
For each criterion, we are using the Fibonacci Sequence evaluation scale as the most suitable for story point estimation.
Code Knowledge
It’s a development team’s understanding and familiarity with the codebase they are working on. It includes the ability to comprehend and navigate the code, as well as the understanding of the code structure, design patterns, and best practices used in the project.
Code knowledge is critical for a development team because it directly impacts their ability to write and maintain high-quality code efficiently. Teams with more code knowledge can work more quickly and accurately.
In short, code knowledge is a crucial component of a development team’s skill set and directly impacts the quality and efficiency of their work.
1: Author. I’ve written that piece of code—can maintain and explain it.
2: Maintainer. I worked with that code—no questions about how it works.
3: Reachable. I can ask my teammate and read the documentation about it.
5: Documented. I didn’t work on it. We have some documentation about it.
8: Understandable. I didn’t work on it but I learned how it works without significant effort.
13: Challenging. Need significant time to find out how it works. I didn’t work on that code, but I can reach someone who worked on it or find documentation.
21: Never heard about it. No people on your team know that code, or they will leave soon.
Severity
The severity of Impact: Determine how much the technical debt issue affects the software’s functionality or performance. The severity of impact could be high, medium, or low, and this can be used as a criterion for prioritization.
1: No impact at all.
2: Cosmetic: Shallow impact on some local components. Can be addressed in the future when resources and time are available.
3: Minor: It works well, but we can improve it. Can be addressed in the future when resources and time are available.
5: Builder: Slows productivity, makes code less maintainable, or prevents the addition of new features. It can be addressed later when resources allow. Can be addressed later
8: Blocker. Blocks further enhancements or updates to one component of the software. It should be addressed soon to prevent significant issues from arising.
13: Major. Blocks and almost brakes multiple software components. Creates additional risks or delays to the project.
21: Breaker. It renders the software unusable or creates high risk if left unresolved.
Dependency and system scale
How many components depend on that part of the code? The scale of impacted software architecture:
1: Trivial. Can be ignored as it may be repaid at any point.
2: Minor local. It is self-contained in a single method, class, or function. May violate SOLID principles—no significant impact on the software’s overall quality.
3: Moderate local: Impacts multiple methods, classes, or functions. It may also be more difficult to modify without causing unintended consequences.
5: Global. Self-contained in a single application or service but involves SOLID violations across subsystems in a more extensive system that spread to seemingly unrelated areas. It may also include a mismatch between abstraction layers, integration point problems, and hard coupling. This debt does not impact consumers of the application or service, but it is felt when modifying the service itself.
8: Major global. More significant and widespread impact on the software’s quality. It may involve multiple subsystems and impact the entire application or service. It may also be more difficult to modify without causing unintended consequences.
13: Systemic. Spills across multiple applications, infrastructures, or teams. It involves numerous services sharing a data store, high coupling across different bounded contexts, and a stark mismatch between technical implementations and business logic. Systemic debt is untenable in the long term and requires immediate attention.
21: Critical. This poses a significant risk to the software’s overall quality and may impact the system’s stability and reliability.
Cost of fixing
How many story points would it cost to fix the technical debt issue?
1: No effort
2: Low cost: 10% of the sprint duration.
3: Moderate: 20% of the sprint duration.
5: Significant: Half-sprint
8: High: One sprint
13: Very high: More than one sprint, but less than two sprints. Recommended to divide into multiple issues.
21: Prohibitively expensive. No idea now how to handle it. Two sprints and more.
Customize criteria descriptions
Don’t forget that the best criteria descriptions are easier for your teammates to understand. The more specific criteria and scale description you will have — the better for your prioritization process. Specify sprint durations, explanations of dependencies, definitions of blockers, and meaning of code knowledge. Read more about criteria description editing.
Unsuitable criteria for technical debt evaluation
Business value, occurrence, age, and Impact on user experience are unreliable criteria for evaluating technical debt.
Don’t use: Business Value or User Experience
Factors such as code quality, documentation, test coverage, and software architecture rarely directly correlate with business metrics like revenue. These factors affect the ability of the development team to make changes efficiently and the software’s overall quality, reliability, and scalability.
One of the most popular reasons for not maintaining the technical debt is evaluating it in the potential revenue.
Don’t use: Occurrence
Consider the probability of the technical debt issue occurring again in the future. Technical debt is not a bug that may occur again. Don’t waste your time predicting the future.
Don’t Use: Issue Age
That may feel like an evident and straightforward idea to refactor old libraries sooner. But why should you spend time on it if the code works well and doesn’t slow down or create vulnerabilities? Age shouldn’t be your prioritization criterion.
Priority score calculation for the technical debt issues
As usual, we need to balance criteria weights for the right strategy for setting top priorities issues for technical debt. By default, we have weight -2. The fewer dev resource you have on your team — the more negative the weight must be.
The final formula is pretty simple:
Collect issues for technical debt backlog
In “Essential Scrum: A Practical Guide to the Most Popular Agile Process,” author Ken Ruben uses three categories to define technical debt: happened-upon, known, and targeted technical debt.
Happened-upon technical debt is technical debt that the development team did not know existed until it was exposed during routine product use or maintenance. For example, while adding a new feature to the software, the team may discover a workaround that was added to the code years ago and left unchanged, resulting in unexpected behavior. Happened-upon technical debt can also be caused by ‘bit rot,’ which occurs when code deteriorates over time, altering its function and usability.
On the other hand, Known technical debt is technical debt that the development team is already aware of and can see in the software. Examples of known technical debt include poor code quality, lack of documentation, or insufficient testing.
Finally, targeted technical debt is known technical debt that the development team has chosen to address in a specific sprint or release. This might involve revamping code, improving documentation, or increasing test coverage to reduce technical debt and improve the quality of the software.
By understanding the different types of technical debt, development teams can prioritize their efforts and work to address technical debt to minimize its impact on the software’s long-term maintainability and reliability.
Tip 1. Create a dedicated section on your task tracker
It’s essential to have a property to separate tech debt issues from other issues like bugs or features. Use a special tag/label, issue type, or component. You should always have the option to look at the full backlog with all issues and filter it by type.
Tip 2. Use a consistent format
Use a consistent format for logging technical debt issues, such as a user story or a task in your backlog tool. This will help you easily identify and prioritize technical debt issues.
Tip 3. Provide a clear description
Provide a clear description of the technical debt issue, including its impact on the codebase, the estimated effort required to fix it, and any potential risks or consequences.
Tip 4: Use Code Change Frequency for collecting Happened-Upon technical debt
Code Change Frequency is how often changes are made to a software system’s codebase.
It can be used to assess the health and quality of a software project and identify potential issues and risks. It allows for evaluating impact, identifying high-risk areas, and making informed decisions about changing the codebase.
The high frequency may indicate frequent updates, improvements, instability, or errors.
The low frequency may indicate a lack of maintenance or evolution, leading to technical debt and other issues.
Tip 5: Auto-Scan your code for Slowness and Vulnerabilities
There are many tools for code analyses. Try it and push found issues to your task tracker’s backlog.
Code Scene — One tool to visualize, understand and improve your software regarding code, knowledge, and people behind it. Make improvements based on automated, prioritized, and actionable recommendations.
SonarQube: A popular tool that can detect security vulnerabilities, code smells, and other issues in your code. It supports various programming languages and integrates with various CI/CD tools.
OWASP ZAP: An open-source web application security scanner that can detect vulnerabilities such as SQL injection, cross-site scripting, and other security issues.
CodeClimate: A cloud-based platform that analyzes your code and provides insights into its quality, maintainability, and security. It supports various programming languages and integrates with GitHub, Bitbucket, and other tools.
Snyk: A cloud-based tool that scans your code and dependencies for security vulnerabilities and provides remediation advice. It supports various programming languages and integrates with various CI/CD tools.
AppDynamics: A tool that provides real-time insights into the performance of your applications, including response time, error rate, and other metrics. It helps you identify performance bottlenecks and optimize your code.
Qodana. Evaluate the integrity of the code you own, contract, or purchase. Enrich your CI/CD pipelines with all the smart features you love from JetBrains IDEs
Conclusion
Technical debt is inevitable in software development but can also be a significant roadblock to progress and innovation. By developing a technical debt prioritization system that works for your team, you can minimize its impact and maintain the quality and reliability of your software over time.
Remember that technical debt is not just a developer problem; it affects the entire organization. By incorporating technical debt management into your project management processes, you can ensure that everyone is aware of its impact and is working together to address it.
Finally, it’s important to remember that addressing technical debt is not a one-time event; it requires ongoing attention and effort. By regularly reviewing and updating your technical debt backlog, you can stay on top of potential issues and ensure that your software remains healthy and reliable in the long term.
Highly recommended to watch Adam Tornhill’s talk about that idea, “Prioritizing Technical Debt as If Time & Money Matters”