How I get technical debt under control
Applying iterative buffer planning to help tame tech debt.
Technical debt is one of our industry’s favourite buzzwords. It’s the excuse engineers use when they don’t ship on time, and it’s the kind of work that product managers love to push back indefinitely.
The metaphor of debt is an interesting one. It tells us that we can borrow from the future to rush today’s functionality. Rather than shipping clean code, we ship a feature as soon as possible, knowing we’ll have to do some cleanup in the near future. This is the kind of investment that can definitely pay off. A hacky e-commerce solution on Black Friday is more lucrative than a perfect one a week later.
But not all debt is an investment. Just like consumers can get in trouble by taking the Visa card for a shopping spree, software products get in trouble by continuously rushing features without a plan to pay off the debt.
As debt accumulates, productivity grinds to a halt. What should take a week now takes a month to deliver. And rushing features becomes ever more expensive.
As an industry, we are notoriously bad at paying back technical debt, and our agile software development practices are a big part of that.
The backlog, our main tool for planning, is the team’s to-do list. In theory, the most important stuff gets done first. But that’s not what we see in the field. Backlogs are typically managed by product owners/managers, not by engineers. In reality, we prioritize by “business value”– all the stuff business stakeholders find valuable. Technical tickets rank low on that list.
Sure, it helps if vocal engineers can explain why the move from AngularJS to React matters. But that is not enough to keep it on the map. Backlog prioritization incentivizes pushing back non-feature work. You can’t fight a system where the odds are stacked against you– the house always wins. The occasional discipline and willpower are no match for human nature.
In such a system, amassing technical debt without paying it back is natural.
The interesting thing I have learned over the years is that business stakeholders understand the need to address technical debt. But, they have a hard time prioritizing this kind of work. They don’t have the tools to gauge its value and have every incentive to postpone this work.
Most teams struggle to balance feature work with paying back technical debt, so I thought it would be useful to give a practical explanation of how I try to get this under control.
If we look deeper at the metaphor of personal financial debt, it can give us some valuable insights.
Let’s say we have a monthly income of €2000 with these expenses.
The income is our total dev capacity. Rent and utilities are our operational work. We have to do customer support, maintenance, and bug fixes. If we stop paying the rent, we’ll get in trouble soon. The car loan is our technical debt. We get to drive a car today because we can pay it off in instalments over time. That’s a sound investment. It allows us to drive to work, getting us that €2K income. The €700 is our disposable income. It’s what we can spend on features.
If we follow the metaphor, it becomes obvious that paying back technical debt has to come on top of operational work! It’s not enough to plan Recovery Blocks and hope the tech debt gets resolved. We can’t use our rent money to pay off the car.
The crucial takeaway is that technical debt gets paid back in Focus Blocks, not Recovery Blocks. Recovery is for operational work. While you are getting rid of AngularJS, bugs and support tickets keep rolling in. So, treat paying back technical debt as a feature and dedicate a Focus Block to it.
If paying back requires more than a few weeks, you can revisit it with a second Focus Block later down the line. Even if you have to plan 10 blocks spread out over the year, at least your technical debt is planned. That’s a lot better than the misguided good intentions we see so often. The size of these down payments is a good factor in calculating the ROI of taking on technical debt in the first place. Is rushing this feature for the trade show worth 4 weeks of Focus Blocks in the coming months? By putting that on the roadmap, we can see the impact this has on our other deliverables. It also allows us to project an end date for the loan. After week 5, AngularJS is history.
If only a part of your team can work on paying back the technical debt, you can mix it in with a Recovery Block. This is common in cross-functional teams where e.g. the backend devs can’t contribute to the React migration. They get to do some operational work instead.
By planning technical debt on the roadmap, you get a very good feel of the impact it has on your team’s productivity. We can see what taking out the car loan does to our disposable income. This can be extremely confrontational. Nobody wants to be in a situation where they need to spend 50% on Recovery and 25% on Tech debt. That leaves little time for features! But hiding that in a backlog and passing the buck indefinitely isn’t going to help either.
So, by visualizing this on the roadmap, teams can start an honest conversation with their business stakeholders. Let’s stop agreeing that we need to spend some time on getting rid of AngularJS this year. That’s a good intention, not a plan. Let’s map it on the timeline and see what the impact is on the feature work.
That’s the only way to get technical debt under control.