The Tax You Pay Without Seeing the Bill
Every product carries a hidden tax. It does not appear on a roadmap. No one approves it in a planning meeting. But it gets paid, in slower releases, in engineers who spend a day on what should take an hour, in bugs that escape because the code is too tangled to test confidently. The tax is tech debt and the bugs that live alongside it, and the reason it is so dangerous is precisely that you do not see the bill arrive. It is withheld at source, quietly, from every future thing you try to build.
Most PMs handle this badly. They either ignore quality entirely until something breaks, or they become the person who brings up tech debt in every meeting until colleagues tune them out. Neither works. The first lets the tax compound until it strangles the team. The second turns a real concern into background noise that engineers and executives learn to discount.
This essay is about the third path: thinking clearly about debt and quality, making the invisible visible to people who control resources, and negotiating paydown without sounding like a broken record. The goal is not to eliminate debt, which is neither possible nor desirable. The goal is to manage it the way you would manage any other liability on a balance sheet you actually understood.
What Tech Debt Actually Is
The phrase gets thrown around loosely. Engineers call any code they dislike "tech debt." Executives hear it as "engineers want time to clean up after themselves." Both are wrong, and the looseness is part of why the conversation goes nowhere.
The original metaphor, from Ward Cunningham, is precise and worth recovering. Debt is what you take on when you ship something you know is not quite right in order to get to market faster. You borrow against the future to buy speed now. Like financial debt, that can be a smart move. A startup that ships a hacky version and learns whether anyone wants the product has spent its borrowed time well. The problem is not borrowing. The problem is borrowing without ever intending to pay it back, and letting the interest accumulate until it consumes your capacity.
Debt Is Not the Same as Bad Code
This distinction matters. Code can be bad without being debt, and code can be debt without being bad. A module written quickly but in an area no one will ever touch again is not really debt; the interest rate is zero because you never return to it. A beautifully written abstraction in your hottest code path that turns out to be wrong for how the product evolved is genuine debt, even though it looks clean.
Debt is about the gap between how your system is built and how it now needs to behave, weighted by how often you have to work in that area. The interest you pay is the extra effort every future change demands because of that gap. This reframe is useful because it tells you which debt to care about: not the ugliest code, but the code that sits in the path of where you are going next.
Deliberate Debt and Accidental Debt
Martin Fowler's quadrant is the most useful model I know here, and it is worth carrying in your head. Debt comes in two flavors along two axes: was it deliberate or accidental, and was it prudent or reckless.
- Deliberate and prudent. "We know the right way to do this, but we will ship the shortcut now and fix it next quarter." This is healthy borrowing. It is the kind every good team takes on consciously.
- Deliberate and reckless. "We do not have time to do it right, so we are not going to." This is borrowing with no repayment plan. It feels like speed and is usually just damage.
- Accidental and prudent. "Now that we have built it, we understand how it should have been done." This is the unavoidable debt of learning. You could not have known better at the time. It is the cost of doing real work in an uncertain domain.
- Accidental and reckless. "What is a layered architecture?" This is debt taken on by a team that does not know what good looks like, and it is the most expensive kind because no one even sees it accumulating.
As a PM, your job is mostly to keep the team in the deliberate-and-prudent box and to recognize when you are drifting into deliberate-and-reckless under deadline pressure. When an engineer says "we can hit the date but we will be cutting corners," the right question is not "can you do it anyway?" It is "what corner, and what does it cost us to leave it cut?" That converts a vague tradeoff into a decision you can actually make.
The Compounding Cost
The reason debt is dangerous is the same reason compound interest is dangerous: it is slow, then sudden. For a long time, a team carrying debt looks fine. Velocity is acceptable. Features ship. Then a threshold gets crossed, and suddenly everything is hard. The estimate for a small feature comes back at three weeks. Engineers start every sprint by saying "this touches the billing system, so it is going to be painful." New hires take months to become productive because the codebase is a maze of special cases no one can explain.
What happened is that the interest finally outgrew the principal. Each piece of debt made the next change a little harder, which encouraged another shortcut, which added more debt. The cost did not rise linearly. It compounded. And by the time it is visible in your velocity, you are deep in it.
Why You Cannot See It Coming
The cruelty of compounding debt is that the warning signs are diffuse. There is no single day the system breaks. Instead there is a slow rise in the friction of everything, and friction is hard to perceive because it has no fixed baseline. Engineers adapt. They start estimating in the new, slower currency. They forget that this used to be faster. The new normal feels normal.
This is why you cannot rely on the team to raise the alarm at the right moment. By the time the pain is acute enough to complain about loudly, the paydown is enormous. Part of your job is to notice the trend before it becomes a crisis: estimates creeping up for similar work, the same subsystem named as the source of pain again and again, a rising share of effort going to keeping things running rather than building new things.
Bugs: Triage and Severity
Bugs are debt's louder cousin. Where debt is silent, bugs are visible, which paradoxically makes them easier to mishandle. A loud bug grabs attention out of proportion to its impact; a quiet one that corrupts data for a small segment gets ignored because no one is shouting. The discipline that fixes this is honest triage.
Severity Is Not Priority
The single most common mistake in bug handling is conflating severity with priority. Severity is about the bug's impact when it occurs: does it lose data, block a core flow, or merely misalign a button. Priority is about whether you should fix it now, and that depends on severity multiplied by frequency multiplied by who is affected. A cosmetic bug on your highest-traffic page might outrank a data-loss bug that only triggers under a configuration two customers use.
Keep these separate in your head and in your tracker. A useful default severity ladder:
- Critical. Data loss, security holes, or a core flow broken for many users. Stop and fix now, whatever else is happening.
- High. A meaningful function broken or badly degraded, with no acceptable workaround. Fix within the current cycle.
- Medium. Something is wrong but users can work around it, or it affects a narrow segment. Schedule it; do not drop everything.
- Low. Cosmetic or edge-case issues that annoy but do not block. Batch these; fix when you are already in the area.
The Bug Backlog Is a Decision, Not a Failure
Teams often treat an open bug as an indictment. It is not. Every product of any size has more known bugs than it will ever fix, and that is fine. The unhealthy state is not having open bugs; it is having an undifferentiated pile of them that no one has triaged, so the critical issues drown among the cosmetic ones. A backlog you have ranked is a set of decisions. A backlog you have not is a liability waiting to surprise you.
Making Invisible Work Visible
Here is the central problem. Debt paydown and quality work are invisible to the people who control resources. A new feature is visible: there is a demo, a launch, a metric that moves. A refactor produces none of that. The system does the same thing it did before, just more maintainably. To a stakeholder watching outputs, you spent two weeks and shipped nothing. This is why quality work loses every prioritization argument it is not deliberately defended in.
Your job is to translate the invisible into terms the business already cares about. Engineers will tell you the code is messy. That sentence has zero leverage with an executive. The same reality, translated, has plenty: "The checkout system is built in a way that makes every change risky and slow. The last three features there took twice as long as estimated, and two of them caused incidents. If we restructure it, the next several quarters of payment work get faster and safer." Now you are not talking about clean code. You are talking about velocity, risk, and the roadmap they already approved.
Tie Debt to the Roadmap, Not to Principle
The weakest case for paydown is "we should fix this because it is the right thing to do." It is true and it never wins, because every other request is also framed as important. The strongest case is "this debt sits directly in the path of something on our roadmap, and paying it down makes that thing cheaper and faster." Debt that blocks nothing on the plan can usually wait. Debt that taxes everything you are about to do is worth fighting for, and the fight is winnable because you are arguing in the currency of goals everyone already shares.
Quantify the Interest
You do not need precision, but you need numbers. "Things are slow" is unpersuasive. "Estimates for work in this subsystem have roughly doubled over the past year, and a third of incidents trace back to it" is a case. Pull whatever evidence exists: estimate-versus-actual drift, incident counts by area, the recurring appearance of the same subsystem in retrospectives. The goal is to convert a feeling shared by engineers into a pattern visible to everyone.
The Quality Budget
The best teams I have seen do not fight the debt battle feature by feature. They establish a standing allocation, a quality budget, and they protect it. Some fixed share of every cycle, often somewhere between ten and twenty percent, goes to debt paydown, bug fixing, and internal tooling. The exact number matters less than the principle: it is a baseline, not a leftover.
The reason a standing budget works better than case-by-case negotiation is that it removes the per-decision argument. If quality work has to win a fresh prioritization fight every cycle, it loses most of them, because there is always a louder feature. A budget makes the decision once. Within the budget, the team allocates to whatever debt and bugs matter most right now. Above the budget, in a real crisis, you can still surge. But the floor holds.
When the Budget Is Not Enough
Sometimes debt has compounded past what a steady budget can address. The subsystem is so far gone that incremental cleanup cannot catch up. This calls for a different move: a dedicated, time-boxed investment with a clear goal and a clear end. Not "we will clean things up" forever, but "we will spend six weeks restructuring the payment system so that the next year of payment work is faster, and here is how we will know it worked." Open-ended cleanup projects are where credibility goes to die. Time-boxed ones with defined outcomes are how you earn the right to ask again.
Negotiating Paydown Without Becoming Noise
The PM who raises tech debt in every meeting gets ignored, not because the concern is wrong but because constant alarm is indistinguishable from no alarm. If everything is urgent, nothing is. The skill is choosing your moments and bringing evidence when you do.
Pick Your Battles by Leverage
Do not advocate for paying down all debt. Advocate for the specific debt with the highest leverage: the debt in the path of the roadmap, the debt generating the most incidents, the debt slowing the most-touched code. When you bring one well-evidenced case instead of a general complaint about quality, people listen, because you are clearly exercising judgment rather than reflexively defending engineering.
Use the Moments the Business Hands You
The easiest time to win paydown is when the business is already feeling the pain. A major incident, a feature that came in at triple its estimate, a customer escalation traced to a known weakness: these are openings. The cost has just become visible on its own. Your role is to connect that visible pain to its underlying cause and propose a proportionate fix, while the memory is fresh and the appetite exists.
Be Willing to Lose Gracefully
Sometimes the business will choose speed over quality even after you have made the case well. That is a legitimate decision; you do not own it alone. When it happens, do not sulk and do not relitigate it weekly. Document the decision and its expected cost, and let it stand. If the predicted cost materializes, you now have evidence rather than an "I told you so," and evidence is what wins the next round. The PM who accepts a loss cleanly keeps the credibility to win later. The one who never lets it go becomes the broken record everyone learned to ignore.
A Final Word
Quality and debt are not a moral crusade. They are a balance sheet. Some debt is smart, taken on deliberately to buy speed you needed. Some is reckless, accumulated by default until it strangles you. Your job is not to eliminate the liability but to understand it, keep it deliberate, and pay it down where the interest is highest. Do that and you will never be the broken record, because you will only speak up when you have something specific and evidenced to say.
The PMs who handle this well are not the ones who care most about clean code. They are the ones who translate invisible work into visible stakes, who tie paydown to the roadmap rather than to principle, and who protect a standing budget so the question gets answered once instead of fought forever. Treat the unseen cost as real, measure it as best you can, and spend against it deliberately. That is the whole discipline.
Key Takeaways
- Tech debt is the gap between how your system is built and how it now needs to behave, weighted by how often you work in that area. It is not the same as ugly code; care about debt in the path of where you are going.
- Keep debt deliberate and prudent. When a deadline forces a shortcut, ask what specifically you are borrowing and at what interest rate, not just whether you can still hit the date.
- Debt compounds quietly, then bites suddenly. Watch for creeping estimates and the same subsystem named as the source of pain again and again, before it becomes a crisis.
- Separate bug severity from priority, and treat the choice not to fix a bug as a recorded decision rather than a default. A triaged backlog is a set of decisions; an untriaged one is a liability.
- Make invisible work visible by translating it into velocity, risk, and roadmap terms, then protect a standing quality budget so paydown is decided once rather than fought every cycle.