
Привет, Хабр! Меня зовут Саша Мищенко, я тимлид платформенной команды в Профи.ру. Сегодня хочу поговорить о легаси — о том, как мы к нему относимся и как уживаемся в одной компании.
Чего точно не будет в этом тексте: страшилок о том, как мы потеряли кучу денег из-за старого кода, и геройских историй про то, как я проснулся и решил переписать всё с нуля.
Вместо этого я хочу рассказать:
почему мы не переписываем код просто из-за того, что он старый;
как балансируем между быстрыми релизами и долговечной архитектурой;
какие фейлы происходят, когда команду уносит в одну из крайностей.
Поехали.
Зачем вообще снова говорить о легаси?
Пока мы пишем код, тема легаси будет на поверхности. Любой разработчик в среднем и крупном бизнесе живёт с одной и той же мыслью: «Надо бы побыстрее, но не хочется влезать в техдолги».
Это может пугать, расстраивать и дизморалить. Но легаси есть почти везде. Если код живёт достаточно долго, он становится частью истории продукта. Меняются разрабы, требования рынка, стек, а кодовая база, как верблюд, тянет на себе всё это разнообразие времён и подходов.
Есть пруфы: 64% важных для компаний инструментов написано на легаси. До сих пор! И у этого есть причина: золотое правило — «Не сломано — не трогай».
25 лет назад Джоэл Спольски предостерёг разработчиков от полного переписывания кода, который работает. Всё ещё актуально (но не всегда).
В старом, с виду страшненьком, но рабочем коде живут накопленные годами знания, обработка корнер-кейсов и следы того, как ведут себя реальные пользователи. Выкинул функцию на 200 строк — и внезапно выяснил, что она держала на себе половину сервиса.
Если уж и переписывать, то за что-то очень понятное и осязаемое: скорость поставки, безопасность, масштабирование. Да и то постепенно.
Но иногда соблазн велик: выбросить всё, создать новую папку и на год исчезнуть в прекрасной новой архитектуре. Признайтесь, бывало такое желание?
О фейлах и людях
Не буду говорить о старых известных кейсах вроде Netscape: хочется свежих историй.
14 июля Cloudflare уронила публичный резолвер 1.1.1.1 на 62 минуты. Корень проблемы — баг от 6 июня. Пока систему не трогали, он себя не проявлял. Но когда запустили общее обновление, то оно сузило список рабочих площадок до одной, тестовой. И она, естественно, была недоступна, потому что предназначена для теста. Отсюда и массовый сбой.
При чём тут легаси? Поломка случилась на стыке старой и новой систем, которые вместе управляют инфраструктурой. Старая часть опиралась на жёсткие списки дата-центров и не умела выкатывать изменения постепенно, поэтому ошибка ударила сразу глобально.
Из хорошего: в Cloudflare быстро восстановили анонсы по всему миру. Но, что самое главное, они написали подробный postmortem. Рассказали о том, что случилось и как так вышло. Это сработало, в основном пользователи даже не разозлились:

Или вот:

Есть и другой кейс, обезличенный, но не менее показательный. Пользователь ИТ-форума рассказал, как в его стартапе с выручкой $100 млн решили всё переписать на микросервисы на Ruby.

Чтобы ускорить миграцию, на несколько лет фактически запретили коммитить в основной сервис. Ожидаемого положительного влияния на выручку не произошло — наоборот, она снизилась.
По итогу вся эта авантюра съела весь раунд инвестиций (Series D) и три года разработки. Пу-пу-пу…
И в целом неудивительно. Нашёл исследование от VFunction за 2022 год, где говорится о том, что 79% попыток модернизировать кодовую базу проваливаются. Конечно, за три года ситуация могла измениться, но не факт, что в лучшую сторону. Может быть, риски и стали меньше благодаря возможностям ИИ, но сам человеческий подход остался прежним — 100%.
Делаю такой вывод из ещё одного свежего (почти) кейса.
Ситуация. У компании есть легаси-дашборд: до первого рендера — около четырёх секунд ожидания с белыс экраном, а ещё старые виджеты. Приняли решение починить.
Разработчики ожидаемо предлагали менять итерациями, но бизнес попросил быстро, красиво и сразу.
В итоге сломали биллинги по триалам, удалили фичу, которая оказалась очень даже нужна юзерам, и словили кучу багов разом.
Из плюсов: вынесли важные уроки из этой ситуации и больше так не делают. Из минусов — всё остальное.
Модернизация с хорошим концом
Но мир легаси не без чудес. Вот парочка свежих примеров.
Весной 2025-го исследователи взяли большой кусок COBOL и прогнали его через LLM-пайплайн, чтобы получить эквивалент на Java. Чтобы было проще читать и легче масштабировать.
Каждый файл при этом проверили через автотесты.
В итоге 93% переведённых модулей после сборки и тестов вели себя так же, как исходник. Для сравнения: ручками получилось ~75%.
Да ещё и намного быстрее.

Не всё, конечно, шло гладко: иногда ИИ не справлялся и путался в коде. Но с такой точностью можно и потерпеть.

Почитать подробнее о кейсе можно тут.
Аналогичная история у Google. Благодаря LLM они смогли провести внутренние миграции и перейти с 32-битных цифр на 64-битные. Вручную это бы заняло вечность.
Как это делают профи
Но оба предыдущих кейса — не о переписывании кода с нуля, а о точечных модернизациях. Для меня это единственный безопасный вариант, и я железно придерживаюсь его в Профи.ру.
Пришло время рассказать не о том, как у других, а о том, как у нас.
Внутри мы разделяем разработчиков на два больших кластера: продуктовую и платформенную команды.
Продуктовые отвечают за новые фичи и поддержку действующего функционала — за всё, что видит или увидит пользователь.
Мы, платформенная команда, работаем на скорость и качество поставки этих фич: Development Experience, пайплайны, архитектурные правила, линтеры, пресеты, дизайн-система.
Для чистоты архитектуры у нас есть несколько инструментов.
Живая база знаний с инструкциями. Это экономит часы и дни онбординга: прислал ссылку — и человек не дёргает коллег по пустякам. Косяки случаются, но мы над этим работаем.
Дизайн-документы. Если кто-то предлагает новую техническую фичу, он пишет текстом: зачем это нужно, какие альтернативы рассматривались, как будем поддерживать, как это повлияет на пользователей и на команды.
Док проходит ревью, и разработчики его либо принимают, либо отклоняют и отправляют создателя подумать ещё. Часто уже на этапе письма автор видит тонкие места, которые в голове были незаметны. Лайфхак: сначала пропишите свою гениальную идею на бумаге — возможно, вы вообще передумаете её презентовать.
Код-стайл. Автоматизируем всё что можно. У нас есть подход: если новое правило нельзя проверить и применить автоматически, велика вероятность, что оно не будет работать в реальности. Значит, мимо. В общем, стараемся использовать готовые пресеты, линтеры и codegen.
Например, для контроля зависимостей в архитектуре используем eslint-plugin-boundaries, а для проверки кода — @typescript-eslint/recommended.
А ещё у нас есть Storybook. В нём мы делаем всё то же, что и остальные, плюс нашли бонусную фичу для тестирования. Например, если крестик у модалки не работает в продукте, тестировщик открывает компонент в Storybook, быстро понимает, что это (баг UI-Kit или продуктовой логики), и относит его туда, куда нужно. Минимизируем пин-понг, где QA отсылают то в один отдел, то в другой.
А теперь о том, что у нас по легаси.
Frontend: Redux → React Query + Jotai
У нас был тяжёлый, неповоротливый Redux с кучей мидлвар и пугающими редьюсерами. При архитектуре feature-sliced, а у нас именно такая, он только мешал. Мы понимали, что масштабировать его дороже и больнее, чем постепенно убрать.
Теперь работаем на React Query для кеша и серверного состояния, а также на Jotai — для атомарных сторов. Получилось гибко, удобно и понятно. Но признаюсь, легаси-куски на Redux ещё кое-где остались. Пока что собираемся с силами, чтобы заглянуть в эти тёмные переулки.
Веб-платформа: кастом → Next.js
Когда я пришёл, у нас был фронтовый «монолит»: фронт и бэк рядом на Node, свой SSR, свой роутинг. Всё это очень долго собиралось и очень долго релизилось.
Мы пытались не трогать базу, а просто прикручивали фичи поверх, но быстро поняли: лучше не надо. В итоге решили перейти на Next.js, а бэкенд увести в отдельные микросервисы на Node.js.
По части фронтенда я сделал дизайн-док: расписал минусы, боли, влияние на скорость релизов и поддержку. Говорил на языке денег: не «было бы славно», а «станет быстрее и дешевле». Уговорить бизнес получилось, но не с первого раза.
Но это красивые истории, где мы двигались осознанно. А есть история как раз о том, как не надо.
Пару лет назад писали новое клиентское приложение. Пилили фичи, а тесты оставили на потом. По итогу, когда отдали в QA, на нас обрушились около 200 багов — от функциональных до перформанса.
Бизнес был недоволен, сроки выросли втрое, да и разработчиков это сильно демотивировало. Несколько спринтов потратили только на багфикс. Зато усвоили урок: расширили отдел QA и закрепили за каждой продуктовой зоной своего тестировщика. Больше не экспериментируем с пайплайном.
В общем, стараемся учиться на своих ошибках и думать на пару шагов вперёд.
Хочу подытожить историей моего приятеля, ML-инженера из одной шведской компании.
На одном из проектов ему достался веб-сервис на Haskell, ещё до появления LLM. Код сложный — про алгоритмы вычислительной химии. Актуальной документации не было, и спросить не у кого: все старички ушли.
В итоге ему пришлось въезжать в код с нуля и пошагово разбираться в языке. В общем, ситуация показательная: сразу понимаешь, как делать не надо. С тех пор он расписывает задачи, пишет доки и никогда не предлагает в прод что-то супернестандартное, если не знает, кто будет этим владеть и кто будет это поддерживать через год.
Мы поступаем так же. Это скучно звучит, но отлично работает.
Вместо вывода
Легаси — это нормально. Это показатель того, что ваш продукт прожил достаточно, чтобы обзавестись историей. А чтобы код при этом не превратился в болото, следите за:
Скоростью и удобством разработки — CI/CD, выбор инструментов.
Time to market — как быстро фича превращается из идеи в релиз.
Темпом онбординга и фидбэком от новых сотрудников по документации и кодстайлу.

Спасибо, что дочитали. Если у вас есть свои истории о том, как вы балансировали между скоростью и архитектурой, поделитесь в комментариях.
А я в ближайшее время планирую написать подробнее о том, как мы переезжали на RN. Думаю, будет интересно :-)
Комментарии (11)
LeshaRB
12.08.2025 12:13В картинке стул и велосипед, нет ли оптической иллюзии?
Между рулем и сидением идет прямая, но стул как-то странно развернутelzvi
12.08.2025 12:13ну это же в целом как та самая из говна и палок архитектура, которая соединяется черт пойми как, но создаёт иллюзию работы)) ну и справедливости ради чаще всего стабильно работает. до поры до времени
dkuzminov
12.08.2025 12:13Есть гигантская разница между "мы не трогаем код потому что нам не нужно" и "мы не трогаем код потому что боимся". "Не трогай то, что работает" -- это не мудрость, а народное суеверие, в котором, впрочем, много практического смысла. Но этот практический смысл ограничивается теми вещами, которые мы привыкли вовремя выбрасывать и заменять новыми.
Рискну высказать утверждение, что если "код работает, но не знаю как" равно "код не работает", как минимум, в отдаленной перспективе. Мы боимся тронуть то, чего мы не понимаем, прикрываемся "народной мудростью", в итоге инфляция технического долга накапливается, причем совершенно ускользая от нашего внимания. В итоге технический долг убивает, как вовремя не замеченная болезнь: становится уже поздно что-то делать.
Pumppeedd Автор
12.08.2025 12:13Да, всё так.
Но уверен, что треть компаний из самых разных сфер влезает в техдолги не по своей глупости или из-за желания не трогать, потому что работает.
Топы и рук-ли, у которых на первом месте KPI и план по выручке, делают своё дело.
dkuzminov
12.08.2025 12:13И? Я говорю о том, что ВИЧ, если за ним не следить, убивает, вы же "Да, все так, но с нашей системой здравоохранения..." При этом статья называется "ВИЧ вас убьет. Или нет?"
elzvi
12.08.2025 12:13вы как будто дискуссию ради дискуссии на пустом месте решили развить. текст не про это же)
greenork
На картинке со стулом должны быть пики
Pumppeedd Автор
Ну я уж не стал)))) хотя признаюсь, хотелось