Tech Debt Is a Product Decision
Debt has a cost you can name in the features it slows down and the incidents it causes. Argue for paying it in those terms — against the roadmap — not by asking for a refactor sprint.
The ask, the obvious response, and how it goes wrong
Every lesson starts where the work starts: someone asked for something, and the first response that comes to mind has a problem.
How do you get time to fix the code that is slowing the team down, from people who cannot see the code?
In planning, an engineer says: "We really need a refactor sprint. The pricing code is a mess." The PM says: "We have the promo launch in five weeks. After that?"
Technical debt is an engineering concern; engineers know best. Ask for a dedicated sprint, or reserve twenty percent of every sprint for cleanup, and do not let product negotiate it away.
"The code is a mess" is an aesthetic claim to someone who cannot see it. The PM hears "engineers want to stop delivering for two weeks", weighs it against a dated launch, and the launch wins every time.
- "The code is a mess" is an aesthetic claim to someone who cannot see it. The PM hears "engineers want to stop delivering for two weeks", weighs it against a dated launch, and the launch wins every time.
- When the refactor sprint does happen, it has no definition of done. It expands to fill the two weeks, touches things nobody asked about, and ends with "we made good progress". The next request for one is harder.
- The twenty-percent budget gets spent on whatever annoyed each engineer that week, not on the debt that costs the most. It becomes a tax that pays for nothing anyone can point to.
- The pricing code keeps causing incidents — the promo that double-discounted in March — but the incident write-up names a missing check, not the three copies of pricing logic that made the missing check inevitable.
What is really going on
- Debt is only visible through its interest. The mess itself costs nothing; the cost is paid every time someone changes that code — in time, in bugs, in the things that do not get tried because they would be too slow (The Cost of a Feature).
- The interest is denominated in roadmap. Pricing logic duplicated in cart, checkout and the order page means every promo change is made three times and tested three times. The next three roadmap items are promos. That is the cost, and it has a date on it.
- Some debt has no interest. Ugly code nobody touches is not worth paying down, however much it offends. Debt is worth paying when the roadmap is about to walk through it, or when it keeps causing incidents.
- A refactor sprint separates the payment from the reason. Paying debt alongside the feature that needs it keeps the scope honest (only what the feature touches), the value visible (the feature ships faster) and the conversation about product, not about engineering taste.
- Choosing not to pay is also a decision, and a legitimate one — if the product is about to be replaced, or the area will not change for a year. The failure is not carrying debt; it is carrying it without anyone having decided to (Naming the Trade-off).
Debt you can see only through its interest
The pricing logic lives in three places: the cart calculates a total, checkout recalculates it with the payment fee, and the order page recalculates it again for the receipt. Each copy is fine on its own. The cost appears only when someone changes pricing — and then it appears every time.
That is the frame that makes debt arguable. Nobody outside the team can evaluate "three copies of pricing logic". Everyone can evaluate "each promo takes a week longer than it should, and one of them double-discounted".
The argument, in the room
The request for time is almost always lost or won in one or two sentences. The ones that lose describe the code. The ones that win describe the roadmap.
Planning for the next five weeks. The promo launch is the headline item. You want to unify pricing first.
"Before we do the promo, we really need a refactor sprint on pricing. The code is a mess and it is really hard to work with. Two weeks would sort it out."
"The next three roadmap items are promos. The last two each took about nine days, and half of that was making the same change in cart, checkout and the order page — one of them caused the March double-discount. If we put pricing in one place as part of this promo, it takes about two days longer. I expect the next two to take about half as long, and I will track it so we can see."
Pay now, pay with the feature, or carry it
There are three honest options for any debt item, and "leave it" is one of them. What matters is that the choice is made with the cost on the table and written down so the next person can see why.
The roadmap is about to walk through code with known debt. What do we do?
when The feature touches the debt directly and more features in the same area are coming.
cost The first feature is later. Someone has to accept that for the later ones to be faster.
when The debt causes incidents or customer harm regardless of what the roadmap does, and no feature is scheduled to go through it.
cost Harder to justify and to scope; needs a done condition someone outside engineering can check.
when The area will not change much, or will be replaced soon, or the interest is small.
cost The interest keeps being paid. Record the decision and the condition that would change it, so carrying it stays a choice.
A register that speaks roadmap
A debt register is useful only if each entry says what it costs in terms the planning meeting uses, and what would trigger paying it. A list of things engineers dislike is not a register; it is a complaint box.
1## Pricing calculated in three places2 3**Where:** cart total, checkout total (+ payment fee), order-page receipt4**Interest, from the last 6 months:**5- Promo changes: 2 of 2 needed the same change in 3 places (~4 of 9 days each)6- Incidents: March double-discount (totals drifted between cart and checkout)7- Declined: per-item promo pricing, estimated too risky with 3 copies8**Roadmap it blocks:** Q4 promos x3, per-item pricing9**Payment:** one pricing function; checkout and order page read its result10**Done when:** a promo change is made in one file and all three views agree11**Trigger:** next promo item enters planning12**Decision:** attach to promo #1 (agreed with PM, 2026-09-22)Every line is something a PM can check without reading code. "Declined" matters as much as "slowed": the features you did not try are part of the interest.
How to do it
Most important first.
- Name the debt by what it slows or breaks, not by what it looks like: "Every promo change is made in three places" rather than "pricing is a mess".
- Price it in the currency the room uses: days per roadmap item, incidents per quarter, features you have declined because of it. Use the last three changes to that area as evidence, not an estimate of the future.
- Attach the payment to the roadmap item that walks through the debt: "The promo launch is two weeks with the pricing unification, three and a half without, and the next promo is then one week instead of two."
- Scope the payment to what that item needs, with a done condition a PM can check: "Pricing is calculated in one place and the order page reads it." Not "pricing is clean".
- Keep a short debt register with the cost of each item in roadmap terms, and bring the top one to planning when its moment arrives (Decision Records).
How to explain the decision
The sentences, the order, and what to lead with — for someone who did not make the call.
- Lead with the roadmap, not the code: "The next three items are promos. Each one currently means changing pricing in three places."
- Give the evidence from the past: "The last two promos took eight and nine days. About half of that was making the same change three times and chasing the differences. One of them caused the double-discount incident in March."
- Then the proposal, attached to the thing they want: "If we unify pricing as part of the next promo, that promo takes about two extra days. The two after it should each take about half as long."
- Then how you will show it: "We will track days per promo change. If the third promo is not noticeably faster, I was wrong about where the time goes and we will look again."
- "We cannot slow the promo launch." Then do not; ship it as is and pay the three-places cost again. The decision is yours — here is what it costs this time and next time, so it is a decision rather than a default.
- "How do I know the next ones will actually be faster?" You do not, for certain. We will measure days per promo change before and after. If it does not improve, that tells us the time was going somewhere else and I will say so.
- "Why not just do it after the launch?" Because after the launch the next promo is already scheduled, and the debt will be in its way too. The cheapest time to pay is when you are already in the code.
What can go wrong
- Inventing the cost: claiming every change will be twice as fast afterwards, then missing it, which makes the next argument impossible.
- Using the language of cost to smuggle in a rewrite. "It would slow the promo launch" becomes the justification for replacing the whole pricing service.
- Over-attaching: every feature now carries "a bit of cleanup", every estimate grows, and product learns that engineering estimates contain a hidden tax.
- Only arguing for debt that engineers find annoying, and ignoring debt that causes customer harm but is in code nobody on the team likes working on.
- "Debt is always bad and should be paid down." Some debt was the right call when taken and costs nothing now. Paying it is spending time for nothing.
- "If product will not give us time, we will fix it in the background." Unreported work makes every estimate wrong and hides the cost that would justify doing it openly.
- "We need to rewrite it." Rewriting is the most expensive way to pay debt and adds new debt of its own. The question is the smallest change that removes the interest on the next roadmap item.
Knowing whether it worked
- The PM brings up the debt item in planning before you do, because it is on the register with a roadmap cost and they can see the item coming.
- Changes to the area after the payment are measurably faster — by your own before-and-after, not an impression.
- The incident class the debt was causing stops recurring. No double-discount in the two promos after unification.
- Nobody asks for a refactor sprint, because debt is being paid through the roadmap it affects.
- On a small team, the person who writes the promo code also holds the roadmap, and the argument happens in one head. The discipline still helps: it stops "cleaning up" from quietly eating the week.
- At 10x team size, debt in shared code — the pricing library used by five teams — has interest paid by teams who did not incur it and cannot fix it. That debt needs an owner and a cross-team decision, not a line in one team's register.
- At 10x traffic, some debt turns from slowness into risk: code that was merely awkward becomes the thing that falls over under the sale-day load. The currency shifts from days to incidents.
- Debt with no roadmap moment never gets paid. Code that is fragile but rarely touched sits until it breaks, because there is never a feature to attach it to.
- Pricing debt in roadmap terms requires honesty about past changes, including the ones that were slow for other reasons. It exposes estimates to scrutiny.
- Attaching the payment to a feature makes that feature later. Someone has to accept the first item being slower for the next ones to be faster.
Where this applies
Product advice is context-sensitive. These labels say what each claim is specific to, and where a different stage, team or product would differ.
- GENERALPricing debt in terms of what it slows is useful wherever the people deciding priority cannot read the code. It flips when they can — a team of engineer-founders can argue about the code directly.
- STAGE-SPECIFICPre-product-market-fit, much of the code will be thrown away and paying debt is usually waste; take it on deliberately. In a mature product with a long roadmap in the same area, unpaid debt compounds and the calculation reverses.
- TEAM-SPECIFICSome organisations run a fixed maintenance allocation per team by policy. That settles the budget but not the choice of what to spend it on — the roadmap-cost ranking still decides which debt gets the time.
Where the depth lives
This domain teaches the product-side judgement and hands the mechanism off.