Every line of code is a liability. While a technical debt helps ship features faster today, it can become an anchor that drags your entire team down if it’s not dealt with in time. An unmanaged technical debt slows down feature delivery (as developers spend their precious time chasing bugs) and increases frustration among developers.
What is Technical Debt?
Technical debt occurs when teams choose quick solutions over better approaches to ship faster. Similar to financial debt, the amount you pay back due to shortcuts would exceed the amount that you borrowed earlier.
Deciding how to manage tech debt can be gruelling. So, in this post, I’ll provide 3 steps effective strategy to manage tech debt so you can move fast without breaking things.
1. Identify tech debt
Diagnostic is an important step before fixing any issue. Therefore, the goal of this step is to find out the tech debt in the codebase or development workflow.
Warning signs of tech debts:
Delay in shipping features
Increase in bug reports and hotfixes
Developer frustration and turnover
In addition to the above signs, consider these key questions to identify tech debt:
Where do developers waste time?
What code are developers afraid to change?
What slows down feature delivery?
What causes recurring issues in production?
What makes the deployment risky?
Answering each question should give you a list of tasks or areas of improvement to work on.
In my previous role, we faced a significant bottleneck: our front-end build process was entirely manual. Developers had to build the frontend files (JS and CSS) locally and commit them to the git repository. This leads to wasted time and frequent merge conflicts. When we asked “Where do developers waste time?“ and “What slows down feature delivery?“, we identified that our team manually builds frontend files locally. The solution was to set up CI/CD to automate the build pipeline.
2. Measure the impact
Just like how you would pay off debt having a high interest rate sooner, you need to pay down tech debts that are costly for the team earlier. Costly in terms of productivity, time, and energy. Quantifying is not only important but critical, especially for smaller engineering teams with limited resources.
Pause and reflect for a few minutes, and ask yourself (or your team) the following questions to measure the impact:
What’s the effort-to-impact ratio?
Helps to compare the effort required to complete a task versus its benefits.
How often does this problem occur? Daily? Weekly? Monthly?
It reveals the area that would have the biggest improvement in development velocity when the tech debt is addressed.
What’s the risk of not fixing it?
It helps to identify the severity of the tech debt and the implications of not fixing it.
Does this block other work?
Identifies the bottleneck with other teams. It also helps to find out issues slowing down development and deployment.
How does it align with our business goals?
It helps to identify whether resolving tech debt helps to meet business objectives, improve key metrics or make work easier for future.
The above questions help to rank the list of tech debt created in the previous step. It aligns technical resources with business value so you’re not only solving the problems but solving the right problems at the right time.
When we evaluated our manual process of building frontend files locally workflow bottleneck against our impact criteria, the answer was clear:
Effort-to-impact ratio: 1 day to set CI/CD saves 20 minutes per dev per day
Problem frequency: during every deployment
Risk: high change of merge conflict
Blocking: slows down all deployments
Business alignment: faster delivery aligns with quarterly goals
Based on this analysis and a reasonable time estimate for implementation, we made it a top priority to set up the CI/CD pipeline.
Here’s an example tech debt tracking table:
After measuring the impact, add the resulting tasks to project management software for better visibility.
3. Reduce technical debt incrementally
Just like how you won’t be able to pay all debts in one go (unless you win a lottery), it’s not viable for most businesses to hold features development to pay down tech debt. Therefore, an incremental tidying approach is often the best way to pay down tech debt. The reason is that it has a lower risk of failure and higher chances of success.
Lower risk because if you break any part of the software while refactoring, then the impact of that disaster is limited to a small part of the system.
It has a higher chances of success since developers can still deliver value to the business while incrementally fixing the tech debt.
The 3 main approaches to incrementally fixing tech debt are:
i) Make small improvements in your daily workflow
Making small structural improvements daily works best for most teams. Whenever you work on new features or bug fixes, invest a few minutes to hours in improving the design. For example:
Change method or variable names to meaningful ones
Extract a business logic spread across multiple files in one place
Add missing docs
Break down a large file
This approach is effective for both paying down tech debt and maintaining a good software design.
ii) Dedicate time budget to pay down tech debt
Making small improvements won’t be enough to pay down tech debts that have accumulated over the years.
For example, some codebase/workflow improvements such as setting up CI/CD pipeline, removing circular dependency from all services, upgrading from an outdated library to a more recent version, etc. require at least some time.
Therefore, you should roughly allocate 20% of your sprint capacity (1 day a week) sometimes or a full sprint other times to reduce tech debt depending on your team’s capacity.
iii) Strangler fig approach
The strangler fig approach was introduced by Martin Fowler to gradually modernise legacy applications. While modernising (migrating to the latest tools or re-writing) a legacy application, he suggests building new features on top of existing features but in a separate code base. When this is done regularly, the behaviour of the application would slowly migrate from legacy to new codebase and eventually modernise.
For example, you can gradually modernise a legacy project written in JQuery to TypeScript using the strangler fig approach.
Set up TypeScript alongside JQuery
Use TypeScript for new features
Convert the isolated components to TypeScript
Gradually increase TypeScript strictness and add tests for converted features.
Continue until all JQuery codebase is replaced.
It is important to avoid the urge to migrate all JQuery code at once in a large code base as it’s highly risky.
What’s next?
The next step after paying down all major tech debt is to avoid it from accumulating. It is important to promote following team communication strategies to reduce tech debt.
Organise regular tech debt review meetings
Document technical decisions
Standardise impact reporting
Surveys for developer pain points
It may require organisational changes and a developer’s mindset shifts from taking shortcuts to adopting a strategic approach. This is highly discussed in the book “A Philosophy of Software Design”, where John Ousterhout suggests investing 10-20% of development time in improving the overall design. This process may slow you down at the beginning but it will eventually make you 10-20% faster in shipping features later.
Wrapping up
Managing technical debt is a continuous process, not an end goal. By following these three steps - identification, impact measurement, and incremental reduction - teams can effectively balance between shipping features and maintaining a healthy codebase. Remember, the goal isn't to eliminate all technical debt but to manage it strategically. Start small, measure impact, and keep improving consistently.