The post has been translated automatically. Original language: Russian
Technical debt in a startup: how to track it and when to pay it off
"We'll do it in a hurry, then we'll redo it" is a phrase that any team has heard at an early stage of the product. The problem is not the technical debt itself: quick decisions at the start are normal and often justified. The problem is when debt accumulates unnoticeably and at some point each new feature costs many times more than it should. Here's how to work with it without stopping development for the sake of "big refactoring."
1. Name the debt out loud when you create it.
The simplest habit is a comment in the code or a task in the tracker at the moment when you consciously cut a corner: "temporary solution, no error handling," "zachard is finished, put it in the config after the MVP." Without this tag, the debt is simply lost in the commit history, and after six months, no one remembers that this place was a compromise at all.
2. Keep a separate list, rather than lose debt in the general backlog.
The technical debt, mixed with the usual features in one backlog, almost always loses priority — it does not have a visible user who asks to fix it. A separate list (even a simple table) with a brief description and risk assessment keeps the debt in sight of the team and the one who makes decisions on priorities.
3. Link refactoring to a metric, not a feeling.
"The code looks dirty" is a bad reason to spend a sprint on refactoring, because this feeling is difficult to justify to the business. It's much easier to protect refactoring if it's tied to a measurable thing: the time to deliver a feature in this module has doubled in a quarter, the number of bugs in it is an order of magnitude higher than average, and onboarding a new developer in this part of the codebase takes a week instead of a day.
4. Pay the debt in small portions, not in one sprint.
A "refactoring sprint" is almost never agreed upon by the business as a whole and often turns into an endless project with no visible result. The rule works better: 10-20% of each sprint's time is spent paying off the debt from the list, starting with the riskiest item. This is slower, but predictable and does not require separate protection from stakeholders every time.
5. Decide consciously which debt you will never repay.
Not all of the debt needs to be covered. If a section of the code is going to be completely rewritten soon or the module is planned to be cut out in six months, it is not profitable to invest in its refactoring. An explicit "do not touch" solution with an indication of the reason saves time no worse than refactoring itself: it stops endless arguments about when they will finally get their hands on this piece of code.
Technical debt doesn't disappear on its own, but it doesn't require heroic sprints either, if you track it systematically from day one. A useful habit for a team of any size, but especially for one where every hour of development counts.
Технический долг в стартапе: как его отслеживать и когда гасить
«Сделаем на скорую руку, потом переделаем» — фраза, которую слышала любая команда на ранней стадии продукта. Проблема не в самом техническом долге: быстрые решения на старте — это нормально и часто оправданно. Проблема — когда долг копится незаметно и в какой-то момент каждая новая фича стоит в разы дороже, чем должна. Вот как с этим работать, не останавливая разработку ради «большого рефакторинга».
1. Называйте долг вслух, когда его создаёте
Самая простая привычка — комментарий в коде или задача в трекере в момент, когда вы сознательно режете угол: «временное решение, нет обработки ошибок», «захардкожено, вынести в конфиг после MVP». Без этой пометки долг просто теряется в истории коммитов, и через полгода никто не помнит, что это место вообще было компромиссом.
2. Ведите отдельный список, а не теряйте долг в общем бэклоге
Техдолг, смешанный с обычными фичами в одном бэклоге, почти всегда проигрывает по приоритету — у него нет видимого пользователя, который просит его исправить. Отдельный список (даже простая таблица) с кратким описанием и оценкой риска держит долг на виду у команды и у того, кто принимает решения по приоритетам.
3. Привяжите рефакторинг к метрике, а не к ощущению
«Код выглядит грязным» — плохой повод тратить спринт на рефакторинг, потому что это ощущение сложно обосновать перед бизнесом. Гораздо легче защитить рефакторинг, если он привязан к измеримой вещи: время на доставку фичи в этом модуле выросло вдвое за квартал, количество багов в нём на порядок выше среднего, онбординг нового разработчика в этой части кодовой базы занимает неделю вместо дня.
4. Платите долг маленькими порциями, а не одним спринтом
«Спринт на рефакторинг» почти никогда не согласовывается бизнесом целиком и часто превращается в бесконечный проект без видимого результата. Работает лучше правило: 10–20% времени каждого спринта уходит на погашение долга из списка, начиная с самого рискованного пункта. Это медленнее, но предсказуемо и не требует отдельной защиты перед стейкхолдерами каждый раз.
5. Решайте осознанно, какой долг никогда не будете гасить
Не весь долг нужно закрывать. Если участок кода скоро будет полностью переписан или модуль планируется выпилить через полгода — вкладываться в его рефакторинг невыгодно. Явное решение «не трогаем» с указанием причины экономит время не хуже, чем сам рефакторинг: оно останавливает бесконечные споры о том, когда же наконец дойдут руки до этого куска кода.
Технический долг не исчезает сам — но и не требует героических спринтов, если отслеживать его системно с первого дня. Полезная привычка для команды любого размера, но особенно — для той, где каждый час разработки на счету.