Переписать с нуля или чинить: как решить это на уровне инфраструктуры, а не эмоций
Спор «переписать с нуля или дочинить то, что есть» обычно решают на уровне кода: читаемость, тесты, архитектура, сколько раз в код заходили руками поперёк логики. Но половина реальной цены этого решения лежит не в коде, а в инфраструктуре — в том, на чём система работает, как её деплоят и что случится с продакшеном на время перехода. Если считать только код, решение почти всегда получится эмоциональным: «это невозможно поддерживать, перепишем с нуля». Если посчитать инфраструктурную часть цены отдельно, картина часто меняется на противоположную.
Содержание
- Где болит на самом деле: приложение или инфраструктура под ним
- Когда достаточно перенести инфраструктуру, а не переписывать логику
- Двойная бухгалтерия: сколько стоит содержать старое и новое одновременно
- Обкатанная стабильность — это актив, который переписывание сжигает
- Эмоциональная ловушка: «это невозможно поддерживать» — чувство, а не расчёт
- Как посчитать инфраструктурную цену обоих сценариев
Где болит на самом деле: приложение или инфраструктура под ним
Первый вопрос, который стоит задать до любого спора об архитектуре: система плохая сама по себе, или она работает на инфраструктуре, которая её топит? Это разные диагнозы с разным лечением, и их часто путают, потому что снаружи оба выглядят одинаково — «всё медленно, всё падает, никто не хочет это трогать».
Признаки того, что причина в инфраструктуре, а не в коде приложения:
- Версия рантайма или ОС вышла из поддержки.
cat /etc/os-releaseпоказывает дистрибутив, у которого EOL уже прошёл или через несколько месяцев;apt list --upgradable 2>/dev/null | wc -lпоказывает сотни неприменённых обновлений, потому что апгрейд боятся делать — упадёт то, что и так шатко стоит. - Приложение упирается в лимиты железа, а не в архитектуру. Диск забит на 90%, свопится каждую ночь, IOPS упираются в потолок конкретного диска — это чинится заменой инстанса или диска, а не переписыванием бизнес-логики.
- Деплой — это ритуал, а не процесс. Руками зайти по SSH, остановить сервис, скопировать файлы, перезапустить, помолиться. Это боль CI/CD и оркестрации, а не боль кода — тот же код при нормальном пайплайне доставки перестаёт быть источником стресса.
- Зависимости не обновлялись годами, потому что версия рантайма это физически не позволяет — не потому что код плохо спроектирован, а потому что фундамент под ним окаменел.
Если большинство симптомов из этого списка про инфраструктуру, а не про то, как расположены классы и модули в самом приложении, — вывод один: сначала переносите систему на современную инфраструктуру и смотрите, что из «невозможно поддерживать» снимается само. Часто снимается заметная часть: перестаёт течь память из-за старого ядра, перестают падать деплои из-за отсутствия здоровых пайплайнов, обновления зависимостей больше не требуют пересборки всего стека вручную. То, что остаётся после переноса — уже реальный код-долг, а не инфраструктурный шум, который маскировался под «код никуда не годится».
Отдельно стоит явно зафиксировать техдолг инфраструктуры отдельной строкой, а не растворять его в общем ощущении «всё плохо» — про то, как это считать, у нас есть отдельный разбор: цена отложенного обновления инфраструктуры.
Когда достаточно перенести инфраструктуру, а не переписывать логику
Перенос без переписывания работает, когда проблема формулируется в терминах инфраструктуры, а не бизнес-логики: «нам нужна поддерживаемая ОС», «нам нужен современный оркестратор», «нам нужно не бояться апдейтов». В этом случае план обычно выглядит так:
- Инвентаризация текущего стека: версии рантайма, БД, все системные зависимости, cron-задачи, локальные костыли на сервере, которые нигде не задокументированы.
- Контейнеризация приложения как есть, без переписывания бизнес-логики — цель зафиксировать поведение, а не улучшить его на этом шаге.
- Перенос на современную инфраструктуру (новая ОС, современная СУБД той же мажорной ветки, нормальный CI/CD) с приложением, которое по факту не изменилось.
- Только после этого — точечный рефакторинг того, что реально плохо в коде, но уже на стабильном фундаменте, где ошибка деплоя не стоит вам продакшена.
Такой перенос почти всегда быстрее и дешевле, чем переписывание с нуля, потому что вы не платите за две вещи одновременно — миграцию инфраструктуры и переизобретение бизнес-логики. У нас есть отдельная пошаговая инструкция именно по этому шагу: как составить план миграции на новый сервер.
Важная оговорка: перенос не решает всё. Если бизнес-логика реально устарела — правила изменились, домен вырос в пять раз, старая модель данных не выдерживает текущих сценариев, — перенос инфраструктуры только даёт вам стабильную площадку, на которой видно, что чинить дальше. Он не подменяет решение о рефакторинге или переписывании кода там, где оно объективно нужно.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверДвойная бухгалтерия: сколько стоит содержать старое и новое одновременно
Вот пункт, который почти никогда не попадает в оценку «сколько займёт переписать с нуля»: пока новая система не готова, старая продолжает работать, и обе требуют внимания одновременно. Это не разовые расходы, а метр времени, который тикает всё время параллельного существования.
Что входит в двойную бухгалтерию:
- Инфраструктура х2. Серверы, лицензии, мониторинг, бэкапы для старой системы — плюс то же самое для новой, которая ещё не приносит пользы, только тратит.
- Синхронизация данных. Если новая система пишет в свою БД, а старая продолжает быть источником правды (или наоборот), нужен механизм синхронизации, который сам по себе — источник багов и нагрузка на команду, а не разовая задача.
- Двойные инциденты. Продакшен-проблема в старой системе чинится по старым правилам, проблема в новой — по новым, часто ещё не устоявшимся. Дежурный инженер держит в голове два ментальных мира вместо одного.
- Двойной relise-цикл. Фичи иногда приходится катить в обе системы, чтобы не разъезжались по функциональности — это удваивает часть работы разработки на весь период миграции.
- Откладывающийся дедлайн. Переписывание с нуля системно недооценивает срок: пока новая система не покроет 100% старой функциональности, переключиться нельзя, а «последние 20%» почти всегда съедают больше времени, чем первые 80%.
При постепенном исправлении этот период либо отсутствует вовсе (правки катятся в ту же систему, без параллельного окружения), либо он короткий и локальный — вы держите старую и новую версию одного модуля пару недель, а не старую и новую систему целиком годами. Численно посчитайте это заранее: сколько стоит инфраструктура старой системы в месяц, умножьте на реалистичный (не оптимистичный) срок миграции — и сравните с тем, что вы вообще платите за постепенные правки. Часто разница обескураживает именно на этом шаге, ещё до сравнения кода.
Обкатанная стабильность — это актив, который переписывание сжигает
У некрасивого кода, который работает в проде три-пять лет, есть свойство, которое не видно в репозитории: он уже пережил все edge case, о которых команда даже не помнит. Пиковую нагрузку в чёрную пятницу. Странный формат данных от одного клиента 2019 года. Гонку состояний при одновременном обновлении двух записей. Все эти баги нашли и почти наверняка исправили — не элегантно, скорее всего заплаткой поверх заплатки, но исправили, и система с тех пор их не повторяет.
Новая система, написанная с нуля, ничего этого не знает. Она принесёт свой набор проблем — не потому что написана хуже, а потому что любая система, которая ещё не прошла годы реального трафика, статистически обязана столкнуться с классом багов, которые старая система уже отработала. Это не довод против переписывания — иногда оно оправдано, — но это довод против того, чтобы оценивать риск только по качеству нового кода. Новый код может быть объективно чище и всё равно быть менее стабильным в проде первые полгода-год, просто потому что стабильность — это не свойство кода в вакууме, а свойство кода, прошедшего конкретную историю нагрузки.
Инфраструктурное следствие: переключение на новую систему должно идти поэтапно, с возможностью быстро откатиться, а не единомоментным «выключили старое, включили новое». Постепенное исправление старой системы этой проблемы почти не создаёт — оно меняет систему маленькими шагами внутри уже обкатанного окружения, и каждый шаг тестируется на месте, а не всем объёмом сразу.
Эмоциональная ловушка: «это невозможно поддерживать» — чувство, а не расчёт
Желание переписать с нуля почти всегда рождается из усталости, а не из анализа. Инженер открывает файл, видит пять слоёв заплаток без комментариев, чувствует раздражение — и делает вывод «это невозможно поддерживать, давайте перепишем». Проблема в том, что это чувство никак не измеряет реальную стоимость обоих путей. Оно измеряет только то, насколько неприятно сейчас читать этот конкретный файл.
Частный случай этой ловушки — миф, что монолит устарел, а микросервисы автоматически современнее и правильнее. Иногда переписывание с нуля на самом деле означает не «сделаем лучше», а «сделаем модно», и это две разные мотивации с разной ожидаемой отдачей. Разбор этого мифа отдельно — в статье про монолит, который не устарел просто потому что старый.
Проверочный вопрос, который отделяет эмоцию от расчёта: если бы вам нужно было прямо сейчас назвать три конкретных инцидента за последний год, вызванных именно архитектурой кода (а не инфраструктурой под ним, не отсутствием мониторинга, не человеческой ошибкой при деплое) — вы можете их назвать? Если можете и они реально серьёзные — это аргумент за переписывание. Если не можете, а формулировка ограничивается «с этим неприятно работать» — вероятно, вы имеете дело с усталостью команды, а не с объективным техническим тупиком. Усталость команды — реальная и важная проблема, но она чинится по-другому: рефакторингом по частям, улучшением документации, ротацией зон ответственности — а не обязательно полным переписыванием, которое команда та же самая будет делать в том же усталом состоянии.
Как посчитать инфраструктурную цену обоих сценариев
Прежде чем решать, сведите оба сценария в одну таблицу с одинаковыми статьями расходов — не только время разработки, но и то, что происходит с инфраструктурой на всём протяжении перехода.
| Статья | Переписать с нуля | Постепенно чинить |
|---|---|---|
| Инфраструктура старой системы во время перехода | Полный срок разработки новой системы (обычно недооценён) | Не требуется параллельно — правки катятся в неё же |
| Инфраструктура новой/тестовой системы | С первого дня разработки, без отдачи до релиза | Нужна только под конкретные изменения, короткими окнами |
| Риск простоя при переключении | Высокий, единомоментное событие | Низкий, множество маленьких изменений |
| Новые классы багов от необкатанной системы | Ожидаемо высокие первые месяцы | Минимальные — окружение то же самое |
| Стоимость отката при провале | Высокая — откат на всю старую систему целиком | Низкая — откатывается один коммит или релиз |
| Что происходит с командой на время перехода | Двойная нагрузка: поддержка старого + разработка нового | Обычная нагрузка, плюс приоритизация багов |
| Срок до первой пользы | Только после полного покрытия функциональности | Каждое исправление приносит пользу сразу |
Заполните эту таблицу реальными числами по вашей системе, а не ощущениями. Даже грубая прикидка — сколько стоит в месяц текущая инфраструктура, умноженная на реалистичный (а не оптимистичный) срок параллельного существования двух систем — почти всегда даёт число, которое заставляет пересмотреть решение, принятое на эмоциях. Отдельно стоит явно посчитать, во сколько раз может подорожать инфраструктура, если решение «переписать» незаметно превращается в «заодно переедем в другое окружение или в облако» — рост может быть больше, чем ожидается: разбор, почему переезд в облако утраивает счёт.
Практический алгоритм:
- Разделите симптомы на «инфраструктура» и «код приложения» по чек-листу из первого раздела.
- Если доминирует инфраструктура — сначала перенесите систему на современную площадку без переписывания логики, затем пересчитайте, что из «невозможно поддерживать» осталось.
- Оцените реальный (не оптимистичный) срок параллельного содержания двух систем при полном переписывании и умножьте на стоимость инфраструктуры в месяц.
- Сравните это число с суммарной стоимостью постепенных исправлений за тот же период.
- Отдельно оцените риск потери обкатанной стабильности — сколько инцидентов за последний год реально вызваны архитектурой, а не инфраструктурой или процессом.
- Только после этого расчёта принимайте решение — и зафиксируйте его письменно вместе с цифрами, чтобы через полгода можно было проверить, насколько оценка была реалистичной.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Если код действительно ужасен, разве перенос инфраструктуры не отсрочка неизбежного?
Не обязательно. Перенос почти всегда снимает часть симптомов, которые выглядели как проблема кода, но были проблемой окружения — устаревших зависимостей, ручного деплоя, лимитов железа. То, что останется после переноса, — уже честная оценка реального состояния кода, без инфраструктурного шума поверх неё.
Как оценить реалистичный, а не оптимистичный срок переписывания?
Возьмите оценку команды и умножьте её минимум в полтора-два раза — это не точная формула, а поправка на системную недооценку, которая проявляется почти в каждом проекте переписывания: «последние 20% функциональности» стабильно съедают больше времени, чем ожидалось на старте.
Что если старая инфраструктура сама по себе небезопасна — можно ли позволить себе постепенный путь?
В этом случае перенос на современную инфраструктуру — не альтернатива, а первый обязательный шаг, причём срочный, независимо от решения по коду. Безопасность окружения нельзя откладывать до решения архитектурного спора.
Можно ли одновременно переносить инфраструктуру и постепенно рефакторить код?
Да, и это часто лучший вариант — сначала перенос без изменения логики, чтобы зафиксировать поведение на новом фундаменте, затем точечный рефакторинг на стабильной площадке. Это не то же самое, что переписывание с нуля: логика не переизобретается целиком, а меняется управляемыми шагами.
Как понять, что решение принято на эмоциях, а не на расчёте?
Если в обосновании нет цифр — ни стоимости инфраструктуры, ни срока параллельного содержания систем, ни списка конкретных инцидентов, вызванных именно архитектурой, — решение почти наверняка мотивировано усталостью от чтения кода, а не объективным анализом издержек обоих путей.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →