09 · Managing Technical Debt & Platform Investments¶
Technical debt is the one roadmap item that has no customer, no revenue attached, no launch, and no demo — and it will still determine whether you can ship anything in eighteen months. Because it has no advocate outside engineering, it gets funded the way charity gets funded: sporadically, on goodwill, and first to be cut.
The PM's job here is not to decide how the code should be structured. It is to make the cost of not fixing it legible in the same units as everything else on the roadmap, so the trade-off is a real decision rather than a losing argument between "customer value" and "engineering wants to refactor". A PM who can say "this is costing us 28 engineer-weeks a year, here is the working" has changed the conversation permanently.
This module covers a taxonomy of debt, how to measure the interest, how to build the business case for a platform investment, and how to decide what to leave broken on purpose.
Not all debt is the same¶
The classic quadrant (Fowler) is worth internalising because it tells you who to talk to and what to change:
| Prudent | Reckless | |
|---|---|---|
| Deliberate | "We ship the simple version now, and we know the cost" — legitimate, needs a written trigger for repayment | "We don't have time for design" — a management failure, not an engineering one |
| Inadvertent | "Now we know how it should have been built" — unavoidable and healthy | "What's layering?" — a capability gap; hiring and mentoring problem |
Only the top-left is really debt, in the sense of a deliberate loan with a repayment plan. And debt is not only code:
| Type | Example at ListUp | Interest shows up as |
|---|---|---|
| Code | 11 marketplace adapters, each written bespoke | Every change made 11 times |
| Architecture | Sync pipeline assumes batch, retrofitted for real-time | New channel work takes 5 weeks not 2 |
| Data | Three definitions of "active account" | Wrong decisions; ops time (Module 7) |
| Infrastructure | Manual deploys, no staging parity | Deploy fear, weekend incidents |
| Test | 41% coverage on the publish path | Regressions reach production |
| Product debt | Four ways to set a price rule, all still supported | Support load, onboarding confusion, every new feature × 4 |
| Process debt | Every launch checklist reinvented | PM time (Module 7) |
Product debt is yours outright. Nobody else will propose removing the second-best way of doing something, and it is often the cheapest debt in the building to repay.
Measuring the interest¶
Debt is only fundable when its cost is a number. Four measurements, all available from data you already have:
| Measurement | How to get it | ListUp |
|---|---|---|
| Unplanned work ratio | Share of sprint capacity spent on incidents, hotfixes and rework | 27% |
| Change failure rate | Deploys causing an incident or rollback | 18% |
| Lead time in affected areas | Cycle time for stories touching the debt vs elsewhere | 1.8× longer |
| Incident hours | On-call and follow-up hours, tagged by cause | 14 incidents/quarter × 6.5h |
Convert to money once, and reuse it forever. ListUp's engineering team is 9 engineers. At 46 productive weeks a year that is 414 engineer-weeks annually, or 103.5 per quarter. At a $175,000 fully loaded cost, one engineer-week is $3,804.
| Line | Calculation | Value |
|---|---|---|
| Unplanned work | 414 × 27% | 111.8 eng-weeks/year |
| Cost of that | 111.8 × $3,804 | $425,250/year |
| Sanity check | 27% × 9 × $175,000 | $425,250 ✓ |
Nobody in the company can look at $425,250 a year of unplanned work and call debt repayment a hobby. That single number is the point of the exercise — and the cross-check in the last row is what stops a finance director from dismantling it in the meeting.
Budgeting models¶
| Model | How it works | Best for | Fails when |
|---|---|---|---|
| Fixed allocation | 15–25% of every sprint, permanently | Steady-state teams | Becomes untracked slack with no visible output |
| Debt sprints | One full sprint per quarter | Debt needing coordinated change | Stop-the-world sprints get cancelled under pressure |
| Boy-scout rule | Improve whatever you touch | Small, local, code-level debt | Never addresses architecture |
| Funded initiative | Debt work has its own business case and roadmap slot | Large platform investments | Requires the arithmetic below |
| Dedicated platform team | A team whose customers are other teams | 25+ engineers | Below that scale it starves feature work |
Most organisations need two at once: a standing allocation for the small stuff, plus funded initiatives for anything over about three engineer-weeks. ListUp runs 20% standing plus funded initiatives above 3 weeks.
Make the standing allocation visible. Debt work that is invisible gets cut first. ListUp reports it in the same weekly review as feature work, with the interest metrics above as its outcome measures.
Worked example — the channel adapter framework, funded properly¶
Module 3 computed the breakeven on ListUp's adapter framework using new adapters only: 14 weeks fixed, 5 weeks bespoke versus 2 weeks on the platform, breaking even on the fifth adapter. With only three more channels planned this year, that calculation says don't build it — the three planned adapters save 3 × (5 − 2) = 9 weeks against a 14-week investment, a 5-week loss.
That calculation is incomplete, and it is incomplete in the direction that kills most platform investments: it counts only the principal on future work and ignores the interest being paid on the 11 adapters that already exist.
| Cost line | Before | After | Annual saving |
|---|---|---|---|
| Adapter maintenance (11 channels) | 0.60 eng-wk/channel/quarter = 6.6/qtr | 0.25 = 2.75/qtr | 15.4 eng-weeks |
| Adapter-caused incidents | 9/quarter × 6.5h = 1.46 eng-wk/qtr | 3/quarter = 0.49 | 3.9 eng-weeks |
| Three new adapters | 3 × 5 = 15 weeks | 3 × 2 = 6 weeks | 9.0 eng-weeks |
| Total | 28.3 eng-weeks/year |
| Value | |
|---|---|
| Investment | 14 eng-weeks = $53,261 |
| Annual return | 28.3 eng-weeks = $107,663 |
| Payback | 5.9 months |
| Year-2 return | $107,663 against zero further investment |
The proposal that gets funded is not "we should refactor the adapters". It is: 14 engineer-weeks, paying back in 5.9 months, returning 28 weeks a year thereafter, and here are the four measurements we will re-check at month six.
Written into the proposal before approval:
| Element | Commitment |
|---|---|
| Scope boundary | Adapter interface and shared retry/rate-limit layer only. No changes to the sync pipeline |
| Slice plan | 3 slices of ~5 weeks; 2 existing adapters migrated per slice, value from slice 1 |
| Kill criterion | If migrating the first 2 adapters takes over 7 weeks, stop and re-plan |
| Verification date | Month 6: re-measure maintenance hours, incident count, adapter build time |
| What we give up | One quarter of Growth-tier feature work, named specifically so nobody is surprised |
The kill criterion matters most. Platform projects fail by becoming open-ended, and the only reliable defence is a pre-agreed number at which the team stops and re-plans in public.
At month 6, the actual: maintenance 3.1 eng-weeks/quarter against a 2.75 target (missed slightly), incidents 4/quarter against 3, new adapter build 2.5 weeks against 2. Roughly 24 eng-weeks/year of realised saving against 28.3 forecast — 85% realisation, payback 7.0 months. Report this. A platform team that reports 85% is trusted with the next proposal; one that reports 100% every time is not measuring.
Deciding what to leave broken¶
Not all debt should be repaid. Route every item through this table:
| Question | If yes | If no |
|---|---|---|
| Is the code in an area we will change in the next 12 months? | Candidate | Leave it; debt in frozen code costs nothing |
| Is it causing measurable interest (incidents, unplanned work, slowdown)? | Candidate | Document it and move on |
| Is the component likely to be replaced or sunset within 18 months? | Don't fix — plan the replacement | Candidate |
| Can it be fixed incrementally with value at each step? | Fund it | Break it down first, or don't start |
| Would a customer notice within 6 months? | Fund it now | It can wait a quarter |
"We're going to rewrite it anyway" is a legitimate answer — but only if the rewrite is on a dated roadmap. Otherwise it is how debt becomes permanent.
Sunsetting: the cheapest debt repayment¶
Removing a feature repays code debt, product debt, test debt and support debt at the same time, and it is the intervention PMs are most uniquely able to authorise.
| Step | Action | ListUp example: legacy CSV rule import |
|---|---|---|
| 1. Measure | Accounts using it in 90 days | 34 accounts (1.9%) |
| 2. Value | Revenue and strategic weight of those accounts | $2,700 MRR; 3 are Pro |
| 3. Cost | Maintenance, support, blocking effect | 1.2 eng-wk/quarter; blocks the new rule schema |
| 4. Migration path | What replaces it | Rule templates plus a one-time import tool |
| 5. Notice | Length and channel | 90 days, in-app + email + direct CSM outreach to the 3 Pro accounts |
| 6. Assist | Concierge migration for the top accounts | PM personally migrated 3 accounts |
| 7. Remove | Delete code, tests, docs, dashboards | 1.2 eng-wk/quarter recovered, permanently |
Removal is the only debt repayment with a negative ongoing cost. Budget for one sunset per quarter and the code base gets smaller while the product gets better — which almost never happens any other way.
Talking about it with executives¶
| Don't say | Say |
|---|---|
| "We need to pay down tech debt" | "27% of engineering time — $425,250 a year — goes to unplanned work; here is the largest cause" |
| "The code is a mess" | "Stories in the adapter layer take 1.8× longer than elsewhere" |
| "It'll take about a quarter" | "14 engineer-weeks in three slices, value from slice one, kill criterion at 7 weeks" |
| "We'll be faster afterwards" | "28 engineer-weeks a year back, payback in 5.9 months, re-measured at month 6" |
| "Engineering is asking for this" | "This is on the roadmap because it is the cheapest capacity we can buy this year" |
How It Actually Works¶
Technical debt functions economically exactly like financial debt: it lets a team "borrow" development speed now in exchange for a recurring "interest payment" of slower future development (more bugs, harder onboarding, more time spent working around the shortcut) — the reason it's rational to take on debt deliberately (not just an engineering failure) is that, like financial debt, it can be net positive if the borrowed speed lets you capture a time-sensitive opportunity worth more than the accumulated interest, but it becomes destructive when the "interest" compounds faster than the team pays it down, which happens when a shortcut becomes a dependency for other shortcuts. The mechanism behind why platform investments are chronically under-prioritized against feature work is a visibility asymmetry: a new feature has an obvious, attributable owner and a visible launch, while platform work's benefit (faster future delivery, fewer incidents) is diffuse and only visible in aggregate velocity trends months later — this is a classic principal-agent/attribution problem, which is why platform investment requires either protected capacity (a fixed percentage of every sprint, regardless of feature pressure) or an explicit executive sponsor, since it will otherwise always lose a head-to-head prioritization fight against a feature with a clear, immediate, attributable payoff. Quantifying technical debt "interest" (e.g., tracking incident rate, deploy frequency, or engineer-reported friction surveys over time) matters because without a number, debt discussions default to anecdote, and anecdote systematically loses against a feature request that has a customer's name attached to it.
Exercise¶
- Classify your debt. List your team's ten largest known items into the prudent/reckless × deliberate/inadvertent quadrant, and label the type (code, architecture, data, infra, test, product, process).
- Measure the interest. Get four numbers: unplanned work ratio, change failure rate, lead-time multiplier in the affected area, and incident hours by cause. If any is unavailable, say what instrumentation is missing.
- Convert to money. Compute your team's annual engineer-weeks, cost per engineer-week, and the annual cost of unplanned work. Cross-check it a second way, as above.
- Find your product debt. List every feature with more than one way to do the same job. Count the accounts using each variant.
- Build one full business case: investment in engineer-weeks and dollars, annual return broken into maintenance, incidents and future work, payback in months, slice plan, kill criterion, verification date, and what gets given up.
- Include the existing interest. Compute your case twice — once on future work only, once including the interest on what already exists — and note whether the decision changes.
- Route ten items through the leave-broken table and produce two lists: fund now, and deliberately not fixing (with the reason).
- Plan one sunset through all seven steps, including the exact notice wording and who personally migrates your largest affected account.
- Rewrite one debt request using the executive language table, and take it to the next roadmap review.