HIVE80lab — Ops notes

Tech Debt Register for Small Teams

Tech debt is not a moral failing; it is a loan. Every shortcut you shipped bought speed that day and has been charging interest ever since — rework on every change that touches it, minutes added to every deploy, one more way a 2am page can happen. A register is not a shame list. It is the amortization table: which loans you are still paying interest on, who holds each one, and what event forces repayment. One screen, ten rows. If it does not fit on one screen, you are not tracking debt — you are archiving guilt.

The register: one screen, ten rows, six fields

One row per debt. Six fields, no more:

Ten rows visible, maximum. The eleventh row goes to an archive section — not because it does not matter, but because a register nobody can read in one glance is a graveyard, and graveyards do not get paid.

The interest column is the whole point

Size alone tells you nothing: a two-day debt charging four rework hours a month outranks a two-week debt charging nothing because nobody touches that module anymore. Measure interest in evidence the team already produces — rework hours from the last month, added deploy minutes from the last ten deploys, incident count the post-mortems attribute to it. If you cannot name the interest, the row is a preference, not a debt — and preferences live in the backlog, not the register.

Paydown rides feature work, on trigger

The register does not schedule a refactoring quarter. When a row's trigger fires — the next feature touches that module anyway — the debt is paid inside the feature PR, expand-then-contract style: additive module or interface with parity tests first, delete the old path in the follow-up PR. The person who touches the debt pays the interest or refinances the loan. A row whose trigger has fired and whose feature shipped without paydown gets re-scored at the next weekly review — paid, or escalated with a reason.

Cadence: the weekly review, no new meeting

The register is reviewed inside the meeting you already run — five minutes at the end of the weekly review: re-score interest on any row that caused rework this week, check triggers, archive rows paid since last week with the PR that paid them. Paid rows are not deleted silently; the receipt (the PR link) is the register's credibility.

Five traps

Worked example

A nine-person fintech SaaS, three-year-old codebase. The feared item: payment retry logic duplicated across three services after a rushed migration two years ago. The old way, this would be "the payments rewrite" — a quarter nobody could schedule. Instead the register carries ten rows; the duplicated retry logic shows interest of roughly six rework hours a month plus two near-miss incidents in two quarters, owner: the payments engineer, trigger: "next feature touching payments." The trigger fired six weeks later. Paydown shipped as two PRs inside the feature work: the new shared retry module with parity tests against both old paths, then deletion of the duplicates a week later. Total added to the feature: nine days. Result: zero payment incidents the following quarter, and the register lost its highest-interest row with a receipt. Two smaller rows (a deprecated retry library, an unmaintained PDF generator) were paid the same way when their triggers fired.

Metrics (for the register itself)

From the HIVE80lab kit

Related: the capacity planning template is the same discipline for infrastructure — one row per service, a limit, a trigger; the error budget policy is where debt shows up as spent reliability, and the weekly review checklist is the meeting where the register gets its five minutes.