Metaphors shape the way we think. So when we talk about “technical debt,” it’s easy for us all to draw parallels to different kinds of financial debt—there’s healthy debt (like a mortgage) and problematic debt (like credit card debt). Like financial debt, all of it ultimately needs to be paid off. Otherwise, you can declare bankruptcy and rewrite the code from scratch.
Yet explaining technical debt isn’t always so straightforward. The financial metaphor only gets us so far in understanding what technical debt is, why it matters, and how we can prioritize addressing it.
Let’s take a look into better understanding technical debt with several industry leaders— Yvette Pasqua, CTO at Meetup; Andrea Goulet, CEO at Corgibytes; and Rob Zuber, CTO at CircleCI.. (To watch the full discussion with these leaders on managing technical debt, go here.)
Rethinking Technical Debt
As with any complex idea, it can be difficult to define technical debt. Kellan Elliot-McCrea (previously SVP at Blink Health and CTO at Etsy) has said that the term ‘technical debt’ is “dangerously overloaded.” Most attempts at defining the term only address part of the problem and can be misleading. So when this discussion came up in our roundtable on “Working Effectively With Technical Debt” the panelists settled on the following definition:
Technical debt is anything (code-based, or not) that slows or hinders the development process.
“We define technical debt as anything that creates friction between the developer and delivering their work,” Andrea Goulet, CEO at Corgibytes, says. “It’s anything that prevents a developer from being completely in flow and completely productive.”
“We have a similar definition,” Yvette Pasqua, CTO at Meetup, adds. “We look at things that reduce quality and slow engineers down from being able to ship features.”
A common perspective on technical debt is that it stems from engineers’ carelessness, hastiness, or even sloppiness, often in an attempt to achieve results faster. But while technical debt can result from recklessness (inadvertently or not), it’s can also be leveraged deliberately. (This is where the “credit card” and “mortgage” analogies comes into play—you’re borrowing efficiency now in exchange for having to do more work mending the code later. Just as you can borrow capital in a responsible or careless manner, you can create technical debt strategically or recklessly.)
Martin Fowler’s Technical Debt Quadrant
However, we can take a more empathetic view of technical debt that brings us closer to reality. Sure, sometimes technical debt arises from poorly or hastily written code. It also arises from perfectly well-written code that simply doesn’t serve its function as well as it used to.
In this view, tech debt isn’t necessarily anyone’s fault.
“We look back at the prime directive of retrospectives and no matter what happens, everyone did their best,” Goulet says. “That’s really important because there can be a lot of shame and blame that goes around when you’re dealing with technical debt, and that is incredibly toxic. It’s baked into engineering culture.”
Instead, she views her clients’ technical debt as a very successful mess. “It might be a mess, but it got you to where you need to be,” she says. “Let’s celebrate that, and we can improve it and we can make it faster.”
Goulet has elsewhere drawn a different metaphor for paying down technical debt—it is more like a remodel of your codebase. It doesn’t matter how well you build a house; eventually, you’re going to need to replace the roof. Some features may not age well, and you’ll decide to replace them down the line. That doesn’t mean your original roof or kitchen appliances were faulty at all. You’re simply doing the work that your house needs to last longer. And the same goes for a codebase.
“We’re making ourselves better all the time, and recognizing that that’s asymptotic. We’ll never achieve perfection,” she says. “We’re always going to be striving toward perfection.”
What does technical debt look like?
Let’s go back to the definition above that technical debt is anything that creates friction in the development process. In that case, technical debt can take on all kinds of appearances in the codebase, including:
- Where we cut corners in the past for the sake of a quicker benefit (say, to release a feature)
- Decisions that made sense at the time and now need to be updated
- Areas of the codebase, dependencies, and operability choices that resist change
- Regular routine maintenance
Automation and cognitive load
But tech debt can also take on other forms that aren’t even necessarily tied to a line of code. For instance, Zuber points to other friction points that can slow development teams.
“Absence of automation is a big thing,” he says. “Anytime I’m deploying and then I have to go look at it in production to make sure it worked, that is a waste of time, and someone else making a change won’t know that they needed to look at it.”
He also points to cognitive load—everything engineers or leaders have to carry in their heads in order to be able to do something effectively. “Code complexity is a big part of that,” he says. “If it’s too interwoven, I don’t understand the side effects of the change that I’m going to make.”
Absence of context in daily practices
In the same vein, Goulet adds that the absence of context is a form of technical debt. She branches this form of debt into two types: breadcrumbs and daily practices.
If a developer needs to dive in to a piece of the codebase, it’s helpful if the code is self-revealing or if the developer can reference clear documentation. The code itself may be functional, but if it lacks commit comments or other trails of the original developer’s though process, then a later developer cannot always easily and promptly comprehend the code’s purpose. “It’s the why of the system,” Goulet says. “It comes down to developer operations.”
For daily practices, she gets her clients to ask, “Am I using clear variable names and function names? Am I using test-driven development in a way that makes sense and is supported by management? Am I using solid coding principles and do I know what those are? Do I know how to write clean code? All of those individual practices can add up really significantly.”
And then there are the completely non-technical human factors that contribute to technical debt. “Most of us work on pretty small cross-functional teams,” Pasqua says. “And we see a lot of technical debt around our teams not being able to act autonomously and get stuff done well and get stuff done quickly. We look at what are the things getting in the way of our teams being able to fully change, own, operate and maintain their domain?”
It’s of course impossible to list every single iteration of technical debt. Every codebase and every team will experience their own flair. But if there is a generalization to be made, Zuber points out the challenge of technical debt is that its instances are so often invisible.
“There are probably things that are noticed by engineers within their teams first, but then there are also things that are more death-by-a-thousand-paper-cuts,” he says. “To an engineer, it’s this little bit of overhead. But if you’re looking from a slightly higher level, hopefully you have the kind of metrics and data to be able to say wait a second, every single team is doing this thing and they’re doing it slowly. So as an organization, there’s a need to invest.”
How to prioritize addressing technical debt
Whatever form it takes, technical debt matters because of its impact on the development process and on the user experience. Again, it’s rather like an aging roof: you might not notice it until it starts leaking. It matters to keep on top of your codebase’s upkeep so that its impact doesn’t start costing your organization significantly (whether that’s measured in revenue lost, time, or employee engagement).
Technical debt’s impact
Borrowing from Software Developer and Agile coach Declan Whelan, technical debt impacts engineers, teams, and organizations.
Impacts on individual engineers include:
- Technical debt makes it more difficult to add new software value.
- It makes fixing problems more challenging.
- Getting motivated about working in the code becomes a chore.
- Other job opportunities start looking more appealing.
- At extreme levels, engineers may contemplate a switch in careers.
Impacts on teams include:
- Lower velocity, and greater variance in velocity.
- More rigidity in task assignment.
- Less flow within the team.
- Making reliable plans becomes more difficult.
- Again, lower morale and higher turnover.
Organizational impacts include:
- Reduced value of software assets.
- Greater difficulty in managing the portfolio of those assets.
- Reduced flow in the software value stream.
- Slower and less reliable responsiveness to both customer and internal problems.
- Greater friction (and thus even more technical debt!) between teams and groups.
Of course, you wouldn’t want to wait to address technical debt until you start seeing the worst of these symptoms. But no matter what, you already have technical debt. “Theoretically, the second you ship code, it’s technical debt,” Pasqua says, echoing an axiom expressed by other tech leaders as well.
So how can you be practical in prioritizing the technical debt that needs to be addressed while also continuously shipping new and exciting value to customers?
Use metrics to quantify the business impact of technical debt
Using metrics that indicate when and where your team is being slowed by technical debt, and that also help you recognize when team members are addressing it, is a strategy both Goulet and Pasqua espouse. This information will help you identify the business impact of these problems and manage technical debt initiatives moving forward.
“A lot of this is about identifying what’s the tech debt that’s most useful for us right now,” Pasqua says. “If we want to iterate in a certain area that we think will bring the business really high value and help us hit our company, it probably would be most impactful for us to pay down a lot of the technical debt in that area first.”
“You never have time to do all the stuff you want to do,” she adds, “so prioritize. It’s not about the worst debt, but rather what’s the debt that would be most impactful to tackle first given your company roadmap and strategy.”
Make addressing tech debt an everyday practice
Zuber considers a team’s approach to what he calls “status quo work.” A team’s culture regarding daily and regular functions can have a significant impact on technical debt on an ongoing basis.
“We think a lot about budgeting our effort allocations,” he explains. “The notion that one hundred percent of my engineering team’s time or of every engineer’s time is going to go to feature development is where your problems start. None of us is perfect the first time we write something. We all know as soon as we put something out there, there’s going to be a problem and we’re going to have to go fix that problem. Allocated out a budget in a way that says some percentage of this is always dedicated to maintenance and bug fixing. Some percentage is going to be dedicated to tech debt and clean up, or tech investment.”
“Stop thinking about your software as a project. Start thinking about it as a house you will live in for a long time.” — Andrea Goulet
Assess product life cycles
For Goulet, the considerations for working on technical debt come down to the product life cycle itself. She essentially conducts a risk analysis for both creating and addressing tech debt
“If you’re starting an initiative or launching something and you don’t have very many users, the risk of trying something or accumulating the tech debt is much less,” she says. “But when you then have something that is a mission-critical system that is going to impact tens of thousands of users and your company will lose money because of it, then it becomes more important and more critical. So you always have to weigh the business factors. That’ll help you figure out whether or not you’re investing in an activity that’s going to pay back, or prevent or mitigate problems.”
In essence, creating technical debt is inevitable. You cannot avoid encountering it so long as you continue coding and growing. But addressing technical debt doesn’t have to come at a cost of your forward progress. In fact, if you prioritize your debt by risk and reward—by which areas of the codebase are most critical or most valuable to your organization’s purpose—and incorporate that work as a matter of fact in your team’s regular operating procedure, you can start improving your organization’s functionality and effectiveness almost immediately.
This is far from the end of GitPrime’s wisdom on managing technical debt: listen to our roundtable on “Working Effectively with Technical Debt,” or read about How to Get Buy-In for Addressing Technical Debt, The Value of Quantifying Technical Debt, and Why You Should Consider Technical Debt to be Real Debt.
Get Engineering Impact: the weekly newsletter for managers of software teams
Keep current with trends in engineering leadership, productivity, culture, and scaling development teams.