The short answer
Technical debt is worth paying when it charges interest — when it makes every future change slower. Debt in code that never changes charges nothing, and rewriting it is a cost with no return. The question is not "is this messy?" but "is this messy in a place we keep touching?"
Debt that compounds
- No tests around code you change weekly, so every change needs manual verification.
- A data model that fights every new feature, forcing workarounds that become the next debt.
- Deploys that are risky enough that you batch them, which makes each one riskier.
- A build no one can run locally, so feedback loops take hours.
Debt you can carry
- Ugly code in a stable module nobody touches. It is working; leave it.
- A dependency behind the latest version but with no security issue and no needed feature.
- Duplication that has not yet been wrong twice — premature abstraction costs more than duplication.
How to make the case
Framing debt as "the code is ugly" loses to any feature request, and it should. Framing it as "this specific area makes every change here take three days instead of one, and we change it monthly" is a business argument with a number in it.