In every team I have worked with I have had a conversation with someone (evenly spread between leadership, business stakeholders, engineers, and product) that went something like this:
Them: We have so much tech debt. We will never achieve [initiative A] as long as we are dealing with [clunky old system].
Me: Help me understand what is happening with [clunky old system] that is preventing us from working on [initiative A].
Them: Long description about how the product has been neglected, the customers haven’t been migrated to the new version, and no one at the company knows what the product does anymore or the business rules around it so everyone is afraid to touch it. Very, very rarely some description of actual technical problems or risks.
Me: What has been done to solve any of these problems?
Them: Everyone runs away from them because they want to focus on [initiatives B-W], that’s why we are still buried under all this debt.
Me: Can we put numbers around what [clunky old system] is doing to customer satisfaction, engineering speed, or stability? If we do that, I can make a business case to focus on solving this problem.
Sometimes, that is where the conversation ends. Sometimes, the other person nods encouragingly and then sighs hopelessly when asked for metrics. Sometimes, we put together that business case and go at the problem either directly or as a sanctioned side project. As I have gotten better at product, as I have progressed in my career, I have gotten us to that business case more often. It’s not, just, because I have gotten better at digging into the data. It’s also because I started to reframe and better understand what we have always called tech debt. In fact, I have done this enough I have talked at conferences about this product perspective on tech debt. The most important reframe I have made is understanding where the technical problems end and the product problems begin.
I once had an engineering leader tell me that the only thing he hates more than tech debt is millennials because he doesn’t believe either exists. This comment, in my millennial defiance, turned into a conference talk on the topic of tech and product debt. I recently realized I have never done the blog on it, until now. I will do this in a series of 5 posts. This one will be defining the problem. Then I will do a post for each quadrant of debt in my model including how to identify it and how to solve it.
Start With Understanding
At the beginning of any discussion of old systems, decisions made in the past, and debt I always start with a caution. People create the best solution they can based on the information, resources, and constraints they had at the time. Every developer I have met hates every piece of code ever written, including their own written five minutes ago. We work in an imperfect system. We are constantly living within the theory of constraints (if you want to learn more about this, start with The Goal by Eliyahu Goldratt and Jeff Cox). We can only learn from the past by coming at it with compassion instead of mockery.
Every time we start a project, we start with assumptions. We must. They are a necessity to find a path to go down. As we work through the effort, we learn things. Things we know today will change tomorrow. Who we are and what we know, what we learn, is constantly evolving. Things come into the project that are not under our control, like deadlines and limitations. I have never met an ideal environment or effort and I doubt I will. We have to respect that the people who created the systems we now build on top of also faced similar challenges.
At a company I worked with I managed the engineering team and was the only product person on staff. We were plagued with old systems that didn’t talk to each other well, were used by only a few customers, and took up a disproportionate amount of engineering time. They were a drag on the entire system but they weren’t “important” enough to focus on fixing. I started diving into this problem my interviewing the account teams to learn about these old, hidden horrors. Then I literally printed off pictures of elephants with a name of each piece of debt on each elephant. I hung these elephants around our team so we would have a visual representation of the underlying problems we were facing while tackling features and product development. By making them visible, and funny, we were better able to talk about them and casually discuss why they existed. From here I was able to catalog them into different categories of debt, each of which required a different approach to solve it. This became my debt model. More on this later.
What is Debt
Outside of software development, the word ‘debt’ has a really clear meaning. It’s the implied cost plus interest accrued by delaying a payment. Let’s break that down a little. You have something that I want. That item has a cost. I can’t currently afford to pay that cost. So I take on debt to get the item now and pay for it later. That debt is a financial obligation I have taken on to delay payment. We actually interact with debt every time that we make a purchase with a credit card. Student loans, mortgages, auto loans, bonds, stocks… these are all examples of debt. All debt includes both the principal (the original amount borrowed) and the interest (the cost of borrowing). It is a tool of using future income in the present.
We do this all the time in software development as well. We want to delay paying for something so that in the future when we have more time, tools, resources, or patience we can fix it. Most often I have seen a team “delay payment” in software development because they were uncertain about the right course of action, the complexity was too high for right now, or they were trying to meet an externally opposed deadline.
To be clear, debt isn’t bad in and of itself. There can be a lot of reasons why it is the right decision for any given project, team, or product. But over time, after payment after payment is put on the credit card, it can become crushing if not paid down. Just like in real life, we should look for opportunities to consolidate debt, pay down the debt with the highest interest, and eat the elephant one bite at a time. Just like you go to a credit counselor when your monthly carry gets too high, as product managers we need to do the same thing for software.
In my mind, though, we spend a lot of time talking about “tech debt” and most of the things I have encountered in software aren’t purely technical.
Technical Debt Definitions
I lean on the work of Martin Fowler, the Software Engineering Institute, and Dag Liodden at FirstMark whenever I talk about tech debt. I am not an engineer (though I do sometimes play one in stakeholder meetings). All of their work ended up helping me define my own model for how I think about debt more broadly and I have included links above for each of their original works. All of them think about debt in terms of the code up and the interaction patterns out. What do I mean by that? When thinking about tech debt there is this tendency to start by thinking about the fact that code is a living thing and it degrades over time. This can because over time technology evolves. The underlying versions change, the environment the code is being present in (e.g. the browser for web apps) changes, and system complexity rubs wrong against older parts of the system. Once you have accounted for these things, you start to think about design and user interaction account for changing user expectations, taste, and needs.
This means that debt sits in the architecture, the build, the code, documentation, infrastructure first and in processes, people/skill, requirements, business constraints, or design second. Often environmental changes are a distant third if considered at all. As an engineer, this makes sense. You think about the things you can see and control first. Tech debt comes from prioritizing delivery over implementation.
Product Debt Definitions
As a product person, the things I can see and control happen in the opposite direction. The business environment (e.g. who we sell to and what they need) we are operating in is a living thing and it changes over time. The needs of the market, competition, and business change constantly. What was an innovative new product today in commodity today. We must evolve the software to keep up with the changes in taste, user expectations, and needs, as well as competitive pressures. And over time we lose important indicators of those environmental factors. We lose stakeholders, product strategy, and vision. Symptoms of this include constant firefighting, applications working against each other especially when they are owned by different teams, and “unowned application” lists.
Debt Model
Both tech debt and product look similar in their causes and impacts, but they come from different root causes and, therefore, have different solutions. My model breaks debt into four quadrants, with a category of tech and product debt in each area. Debt is incurred either intentionally (we actively decide to put something off) or accidentally (things change or we made the wrong decision previously). Debt is created externally (external market pressures or industry standards) or internally (individual people or teams). What that looks like this this beautiful 2×2 grid. In the next post, I will dive specifically into Intentional Market/Industry Tech and Product Debt.

Note: I don’t use AI to help write my posts or create example pictures. The debt 2×2 chart is my creation and is also in my Consuming Endangered Pachyderms conference talk. The header image in from my trip to Thailand (yes that’s me) when I rode an elephant. I was also 3 month pregnant.