Article

Erasing tech debt: A leader's guide to getting in the black

When we talk about “technical debt,” it’s easy to draw parallels to different kinds of financial debt, be it healthy debt (like a mortgage) and problematic debt (like credit card debt). It needs to be paid down consistently or else you risk declaring bankruptcy, thus having to wipe slate clean and start over from scratch.

Yet understanding technical debt isn’t always as straightforward as that. The financial metaphor only gets us so far in understanding what technical debt is, why it matters, and how we can prioritize addressing it. To truly comprehend technical debt, we need to shift the ways we think about it.

Rethinking tech debt

 

Kellan Elliot-McCrea has said technical debt is a “dangerously overloaded” term. Most attempts at defining it only address part of the problem and can be misleading. In this report, we’ll operate under the following definition of “technical debt,” as based on discussions with industry leaders and the many written pieces on the subject:

Technical debt is anything (code-based or not) that slows or hinders the development process.

Therefore, anything that creates friction between developers and delivering their work is a form of technical debt. Developers need to be completely in their flow to be completely productive; things that reduce the quality of their output and their efficiency in shipping features is problematic.

Debt accrues both inadvertently and deliberately

A common perspective on technical debt — one that may be influenced by the “careless spending” aspect of the financial debt metaphor — is that it stems from engineers’ hastiness or sloppiness in an attempt to achieve results faster. But while technical debt can result from recklessness (inadvertently or not), it can also be leveraged deliberately.

This is what the credit card and mortgage analogies speak to — engineering teams are borrowing efficiency now in exchange for having to do more work mending the code later. Just as one can borrow capital in a responsible or careless manner, teams can create technical debt strategically or recklessly, as well.

Martin Fowler's Technical Debt Quadrant

 

This perspective brings us closer to a healthy, empathetic understanding of technical debt: It’s not necessarily (or even frequently) a result of a character flaw or personal shortcoming. 

Debt happens inevitably with time

Sometimes technical debt arises from poorly or hastily written code, but it also arises from perfectly well-written code that simply doesn’t serve its function as well as it used to. In other words, quite often tech debt isn’t necessarily anyone’s fault.

That point is critical to stress, because the blame game often follows discussions of technical debt, which can be incredibly toxic to a working environment. Instead of viewing tech debt as a fault, managers can reframe tech debt as a success: The tech debt a team accrues also has gotten them to where they need to be. Even if that debt is a splendid mess right now, a team can still celebrate its progress thus far.

Andrea Goulet compared paying down technical debt to remodeling a house. It doesn’t matter how well you build a house: Eventually, you’re going to need to replace the roof. Other features may not age well, and so they can be replaced down the line. That doesn’t mean the original roof or kitchen appliances were faulty at all. You’re simply doing the work that your house needs to continue to last.

The same goes for a codebase and a team’s processes, especially as your team gets better over time. Strategies and approaches that worked well at one time may simply be outdated or inefficient. Newer methods can replace worn-out ones, and quick, inexpensive solutions can be swapped out for higher-quality replacements as resources allow.

Why addressing tech debt matters

 

If technical debt is inevitable and isn’t necessarily a negative outcome of the development process, then it begs the question: Why does it matter?

Returning to Goulet’s home-maintenance metaphor, a worn-out roof is a natural part of an aging house, but it still needs replaced if the home will continue to be inhabitable. Unaddressed technical debt might get a team by for a while, but eventually the issues will start to affect greater areas of the production process and the codebase.

There are also human considerations on top of organizational ones. Agile coach Declan Whelan shared some ways that technical debt impacts engineering companies on the individual, team and organizational level:

Tech Debt's Impact on Teams, Orgs and Individuals

 

Of course, managers don’t want to wait to address technical debt until they start seeing the worst of these symptoms. But no matter what, an engineering team already has technical debt. An axiom expressed by several tech leaders is that the second a team ships code, it becomes technical debt. Therefore, the crux to addressing it becomes learning how to recognize it.

What tech debt really looks like

 

Let’s return to the definition above that technical debt is anything that creates friction in the development process. Probably the most widely and easily understood forms of technical debt are those that manifest themselves in the codebase itself. But technical debt can also take on forms that aren’t necessarily tied to a line of code.

Automation and cognitive load

For example, the absence of automation and the existence of cognitive load are other friction points that can slow development teams.

Every idea that engineers or leaders have to carry in their heads, or every process that they have to complete manually in order to do their jobs effectively, is something that ultimately slows their progress.

Of course, all engineers will stash some concepts in their minds, and everyone has to do certain things manually. But just as a laptop is created to handle a certain processing load with ease, it will start to bog down with too many programs running. Technical debt that stems from a lack of automation or too much cognitive load can ultimately reveal itself in the code, as well. 

If a codebase grows too complex and interwoven, for example, then engineers cannot possibly understand all the ripple effects of the changes they make; that’s not information they can reasonably bear cognitively while actually completing new code. And vague requirements can also contribute to excessive cognitive load; with an unclear end goal, developers may have to account for too many contingencies and possibilities to move forward with any clarity.

Absence of context in daily practices

In the same vein, the absence of context is a form of technical debt. We break this form of debt into two types: Breadcrumbs and daily practices.

If a developer needs to dive into a piece of the codebase, it’s helpful if the code is self-revealing or 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 thought process, then a later developer can’t easily and promptly comprehend the code’s purpose.

For daily practices, engineers can improve the breadcrumbs they leave by asking, “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 build significant contextual understanding down the line for other engineers.

 

What Technical Debt Really Works With

Human factors

Then there are the completely non-technical human factors that contribute to technical debt. Many developers work on relatively small, often cross-functional teams, and technical debt can accrue when those teams aren’t able to act autonomously and accomplish their targets. Human factors can often impede a team’s ability to fully change, operate, maintain and own their domain.

It’s impossible to list every single iteration of technical debt in any of these forms. Every codebase and every team will experience their own unique version. But if there is a generalization to be made, it’s that instances of technical debt are so often invisible.

With that in mind, let's take a look at how to address technical debt systematically within an engineering team, and also within a wider organization.

How to address tech debt

 

Tech leaders seldom have trouble getting engineers on board with the need to address technical debt. In fact, developers are often the ones reporting it — and at the very least, they feel the symptoms first, as they experience the slowdowns every day.

However, even with engineers on-board with fixing the problem, taking on technical debt as a whole is an overwhelming proposition. So we’ve broken down how to address technical debt into two broad categories: changing attitudes and approaches about the work within the team, and prioritizing the debt to tackle it strategically.

Attitudes and approaches about technical debt

This could also be considered the “people side” of addressing technical debt within the team. Engineers are likely on board with the existence of technical debt, and the need to pay it down. But tangible adjustments on the ground are needed in order to manifest as practical changes in process and workflow.

These are some approaches suggested by industry leaders to aid in altering attitudes and approaches to technical debt within an engineering team.

1. Make sure to have buy-in from engineers first and foremost

In trying to earn buy-in for addressing technical debt, we think about needing to convince or persuade our managers, executives, leaders and other higher-up stakeholders. But what about the engineers on our teams?

It’s easy to assume they will support any initiative to tackle it. But if an engineering team is not aligned around the importance of addressing technical debt, it has a fundamental cultural problem that its leadership needs to address before ever thinking about pitching the idea of addressing technical debt to other departments and stakeholders.

Engineers need to be on board to make any debt initiative matter. Making sure they understand the need for such a project, and are in support of its outcomes (even if not everyone relishes the refactoring work that goes into it), will be invaluable once the team gets buy-in from everyone else.

Besides, your engineering team may have menders already in its ranks — those developers who thrive on the challenge of addressing technical debt.

2. Reframe “technical debt” as “continuous product health”

Yvette Pasqua offered a strategy her organization has used before, which is to remove the term “technical debt” from the vocabulary and replace it with “continuous product health.”

“When we talk about technical debt, it’s as if everyone’s shoulders slump,” Pasqua said. “So we tried calling it continuous product health, and it’s helped us so much to get people thinking and talking about it as just a healthy, happy part of what you do every day.”

Teams can consider this long-term strategy as self-care, because it resembles a long-term focus on health, like going to the gym or eating healthy. You don’t just do “healthy” two weeks out of the year; it’s an everyday habit. The same goes with product health.

3. Make addressing technical debt an everyday practice

Carrying the above concept further, making technical debt maintenance a daily (or at least a regular weekly or per-sprint) practice makes this approach part of the status quo. After all, a team’s culture regarding daily and regular functions can have a significant impact on technical debt on an ongoing basis. And recognizing the daily need for maintaining product health will keep technical debt more manageable down the line.

“The notion that 100 percent of my engineering team’s time or every engineer’s time is going to go to feature development is where your problems start,” said Rob Zuber, CTO of CircleCI. “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. You need to allocate out a budget in a way that says some percentage of this is always dedicated to maintenance, clean up and bug fixing.

4. Make “fixing work” and “investment work” first-class citizens

Just as there are introverts and extroverts, there are people who naturally gravitate towards feature work and others who gravitate toward fixing work. We hear these two types called “makers” and “menders,” and building a team with people who enjoy doing both makes ongoing product health maintenance a more efficient process.

Knowing that certain developers on a team relish mending work, managers can plan for technical debt and technical investments with the same level of energy and focus that goes into planning a product strategy or roadmap. Furthermore, they can relate those investments to the company’s larger initiatives by planning strategy hand-in-hand with technical investment, whether that’s on a monthly, quarterly or semi-annual basis.

Prioritizing how you manage your technical debt

 

Whatever form it takes, technical debt impacts the development process and the user experience. And because you create technical debt the moment you ship code, strategizing how to address it can seem overwhelming.

Teams can’t often just drop everything else to clean up the entire codebase. So how can managers be practical in prioritizing the technical debt that needs to be addressed while also continuously shipping new and exciting value to customers?

1. Manage technical debt the same way as financial debt

While the actual process of cleaning up or fixing technical debt may not be as clear as a number in a bank account, the goal is primarily the same as it with with financial debt: Staunch the bleeding, and pay it off incrementally.

First, you need to “cut up the credit cards,” so to speak. When a team is in a tailspin of accruing technical debt, piling more on top won’t help anybody. Teams can’t dig their way out if they continue following the same behaviors and practices they used in the past. So the first step is to find a way to stop those detrimental habits, patterns or processes — in the code or outside of it.

Next, start paying down the debt “one paycheck at a time” — that is, incrementally. An engineer paying down student loan debt wouldn’t allocate an entire month’s pay once a year toward the balance; they are more likely to succeed by paying it down a little at a time with each direct deposit. Similarly, technical investments can be integrated into every sprint. Teams are less likely to get ahead of their debt by allocating only a single stretch of time toward it once a year.

2. Use metrics to quantify the business impact of technical debt

Use metrics that indicate when and where your team is being slowed by technical debt. This information will help leaders identify the business impact of these problems and manage technical debt initiatives moving forward.

“A lot of this is about identifying what’s the technical debt that’s most useful for us right now,” Pasqua said. “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. 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.”

3. Assess product life cycles

The considerations for working on technical debt come down to the product life cycle itself. It’s useful to essentially conduct a risk analysis for both creating and addressing technical 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 technical debt is much less,” Goulet said. “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, it becomes more important. So you always have to weigh the business factors.”

Creating technical debt is inevitable, but addressing technical debt doesn’t have to come at a cost of forward progress. 

In fact, prioritizing debt by risk and reward — by which areas of the codebase are most critical or most valuable to the organization’s purpose — you can start improving your organization’s functionality and effectiveness almost immediately.

Getting buy-in from stakeholders

 

The reasons people in the wider organization often balk at the idea of expending resources to clean up technical debt are understandable. They perceive that paying down technical debt comes at the cost of shipping new features to customers. They can often feel reluctant to support product health initiatives that don’t show immediate external benefit.

The key is to steer discussions around technical debt away from the debt itself and toward terms that matter to key stakeholders. These are some ways to reframe the conversation toward that idea of continuous product health.

1. Get everyone on-board with the trade-offs of an initiative

Every product initiative has trade-offs. The classic “good, fast or cheap” Venn diagram demonstrates this truth expertly. You can get a project done with any one or two of those variables, but all three at once is impossible. 

The question for an engineering leader becomes which debt is acceptable, and when can it be paid down.

For example, a team can either get the functionality to market today, and then invest additional time to make it great or stable later. Or, they can invest the additional time to make it stable now and get the functionality to the market later. It’s a trade-off, and it’s engineering’s responsibility (and in their best interest) to articulate what those trade-offs are

2. Quantify the business impact of investing in addressing technical debt

Engineering leaders typically understand how technical debt in the codebase is slowing down the team’s ability to sustainably deliver product at full speed. But when executives hear that engineering needs to tackle a big refactoring project that will take months, many of them might just see that as dollar bills down the drain. What they need to hear instead is what addressing technical debt will deliver to the organization.

All too often, tales of technical debt are anecdotal. When these problems can be quantified with metrics and translated into dollars lost, conversations with other stakeholders become much more effective.

Using a model such as the Technical Debt Ratio reframes technical debt as an investment in future rewards. Being able to bring that kind of data to the table will help build a more convincing case for addressing technical debt in a strategic way.

3. Present the value to the whole organization

One of the reasons that technical debt accumulates in the first place is that very few organizations have teams or individuals whose purpose is reducing that debt. Everyone has a mission oriented around developing products, enhancing the customer experience, bringing in sales, but seldom does anyone wholly own technical debt.

So once engineering leaders have buy-in from upper-level stakeholders to tackle technical debt, the next step is to enlist those same stakeholders to offer organization-wide support for engineering’s initiatives. High-level support can give engineering teams the greater leverage they need for dedicating time and resources to meaningful debt reduction.

One way to accomplish this sort of buy-in is to plan larger technical debt initiatives at the same time and in the same way that a company plans its product strategy and roadmap. Whether that’s monthly, quarterly, or every half year, doing that hand-in-hand streamlines the process for the organization and increases visibility for the efforts.