Technical debt is not a moral failing; it is the natural residue of building under uncertainty. The code you wrote when you understood the problem less is still there now that you understand it more. Teams do not get in trouble by having debt. They get in trouble by letting it stay invisible until it sets the pace of everything.
Make it visible before arguing about it
Debt hidden in engineers' heads cannot be prioritized, so write it down where work lives: a ticket per known problem, tagged and sized, with a sentence on what it costs, slower builds, fragile deploys, an area nobody dares touch. The list itself changes conversations, because "we should refactor sometime" becomes "these four items cost us roughly a day per week."
Prioritize by interest rate
- Debt in code you change weekly compounds fast and deserves attention first.
- Debt in stable code you never touch charges almost no interest; leave it.
- Debt that causes incidents or data risk jumps the queue regardless of location.
The worst refactoring projects are cosmetic rewrites of quiet corners; the best remove friction from the paths the team walks daily.
Pay continuously, not in grand rewrites
A sustainable pattern is budgeting a fixed slice of each cycle, commonly ten to twenty percent, for debt work, plus the boy scout rule of leaving touched code slightly better. Big-bang rewrites stall because they pause feature delivery for a promise; incremental strangler-style migrations ship value while the old thing shrinks. Tie any large debt effort to a business outcome, faster onboarding, quicker releases, fewer incidents, and report progress in those terms.
Debt is a tool. Borrowing deliberately to hit a market window is smart; the discipline is writing down the loan and scheduling the payments.