Technical debt: when to take it and when to pay
Not every shortcut is debt
Simple code that suffices for the current need isn't debt, even if it isn't general. Debt is a deliberate choice of a solution that will cost more later — duplication known to split, a deferred test, a data structure that won't survive growth.
Bad code written out of ignorance isn't debt but a future bug. The distinction matters because the treatment differs.
When it's worth taking
When you don't yet know if the feature will stay. No point building perfect infrastructure for something that might be deleted in a month.
When there's a real time window — a launch, a customer, a regulation. But then you record what was deferred, where in the code, and the signal that will force a return.
How to pay without stopping everything
“We'll stop for a month and clean up” almost never gets approved. What works: paying as you go — every time you touch a problem area, improve it a little. And allocating a fixed share of every work cycle to maintenance, like you allocate to features.
Prefer to pay in places touched often. Ugly code nobody has opened in two years isn't your problem.
Going deeper
Manage debt in the same tool as tasks, with a tag and the reason it was taken. Debt that isn't recorded isn't debt but a surprise. A practical metric: how long a small change in a given area takes today — if it's climbing, that's the debt talking.