HAIH на практике: как мы заменили legacy-сайт, не перенося его архитектуру
В предыдущей статье про HAIH я описывал идею, которая на первый взгляд звучит немного непривычно для современной разработки с AI: вместо того чтобы строить ещё один фреймворк и пытаться заранее угадать правильную архитектуру, полезнее накапливать инженерные знания — требования, вопросы, принятые решения, ограничения, результаты экспериментов и доказательства того, что решение действительно работает.
До недавнего времени это была в основном методика, проверенная на небольших контролируемых экспериментах. Теперь появился гораздо более интересный тест: настоящий старый проект, который нельзя было просто выбросить и начать с чистого листа.
Речь о Пивной карте — сайте с многолетней историей, реальными пользователями, заведениями, сортами пива, публикациями, комментариями, изображениями и десятками тысяч исторических URL.
Именно на нём мы впервые применили подход HAIH не как эксперимент вокруг нового приложения, а как способ разобрать и заменить реальную legacy-систему.
Не переписывать архитектуру, а восстановить требования
Исходная система накопила несколько технологических эпох. Когда-то сайт работал на MODX, затем части приложения переписывались на собственный JavaScript-стек, появились отдельные frontend и API, Prisma 1 и старая MySQL-база.
Первое естественное желание при такой миграции — сохранить существующую модель данных, поставить перед ней современный API и постепенно заменить интерфейс.
Мы примерно с этого и начали.
Но HAIH предполагает, что архитектура должна следовать из фактических требований, а не из того, что уже случайно существует в репозитории. Поэтому прежде чем закреплять решение, мы исследовали реальную базу.
Там оказалось около 250 таблиц. В них смешались таблицы старого MODX, Prisma relation tables, несколько поколений одних и тех же сущностей, backup-таблицы и другие исторические слои.
При этом реальное предметное ядро оказалось намного понятнее: пиво, заведения, пользователи, публикации, комментарии, изображения и связи между ними.
Это был первый важный результат методики: первоначальная архитектурная гипотеза не прошла проверку реальностью.
Вместо вопроса «как перенести эти 250 таблиц на новый стек?» появился другой:
Какие возможности старого продукта действительно должны пережить миграцию и какие данные нужны для их реализации?
Это принципиально разные задачи.
Brownfield как последовательность доказательств
Рабочий процесс в итоге выглядел примерно так:
legacy system → requirements/capabilities → исследование данных → решения и компромиссы → implementation → verification → production evidence
Мы не пытались сразу объявить всю старую систему спецификацией нового сайта.
Сначала восстановили публичные возможности продукта и его web-контракт. Затем начали переносить вертикальные сценарии: каталог пива, заведения, публикации, участники, комментарии, города, карту, контакты и связи между этими сущностями.
Особое внимание пришлось уделить URL. Для старого публичного сайта адрес — это тоже данные. На него могут ссылаться поисковики, другие сайты, старые публикации и пользователи.
В результате был построен реестр совместимости из 73 760 адресов. Для одного из зафиксированных состояний реализации полный HTTP-обход дал passed: 73760 без ошибок. Отдельно проверялись 11 579 ссылок из контента и 19 660 URL ресурсов.
Это не означает, что любой последующий коммит автоматически покрыт тем же crawl. После него код менялся, и последние изменения проверялись более узкими тестами. Для HAIH это важная оговорка: evidence должно быть связано с конкретным проверенным состоянием, иначе красивое число быстро превращается в маркетинг.
Инвентаризация данных при этом показала масштаб реального содержимого: 1 636 записей пива, 3 797 заведений, 600 статей, 64 города, 3 296 комментариев и 26 548 публичных профилей.
Совместимость не означает копирование
Один из самых полезных выводов этого проекта — совместимость и архитектурное наследование не одно и то же.
Мы сохранили исторические адреса, необходимые публичные данные и связи между сущностями, но не стали воспроизводить всю инфраструктурную историю проекта.
Новая реализация выросла из того же экспериментального runtime, который использовался на HAIH Site, но для реального проекта его пришлось существенно развить.
В production появился единый Express runtime. React Router отвечает за SSR приложения, GraphQL построен на Apollo и Pothos, доступ к существующим данным выполняется через Knex. В development Vite работает как middleware того же сервера. Добавились production static serving, Varnish, обработка старых вариантов изображений через Sharp, ETag, GET/HEAD, корректное завершение серверных ресурсов и другие вещи, которые почти не видны пользователю, но быстро становятся обязательными, когда эксперимент превращается в настоящий сайт.
При этом мы сознательно не стали считать обязательными все возможности старого приложения. Авторизация, создание и редактирование сущностей и ряд других write-сценариев не входили в границу этой миграции. Если они понадобятся дальше, это будут отдельные требования и отдельные задачи.
Так проявляется ещё один принцип HAIH: отсутствие функции тоже может быть осознанным архитектурным решением. Не всё, что накопилось в legacy, автоматически является требованием.
Что получилось в production
Самое интересное началось после выкладки, потому что появились числа, которые можно сравнить с исходной системой.
Основная активная работа над этой итерацией, начиная с 28 сентября, заняла по рабочим таймерам 18 часов 1 минуту.
Эту цифру не стоит превращать в универсальный benchmark «AI переписывает legacy за 18 часов». Проекты различаются, значительная часть понимания предметной области существовала раньше, а сам runtime HAIH развивался до этого проекта.
Но как Time to Capability для конкретного эксперимента это важное наблюдение: за этот промежуток был получен работающий production replacement с реальными данными и широкой URL-совместимостью.
Lighthouse до и после миграции показал:
| Метрика | Старый сайт | Новый сайт |
|---|---|---|
| Performance | 49 | 93 |
| Accessibility | 75 | 100 |
| Best Practices | 74 | 96 |
| SEO | 83 | 100 |
Ещё показательнее оказался runtime.
Старый application layer в одном из production-снимков потреблял примерно:
- frontend — 588,4 MiB;
- API — 231,3 MiB;
- Prisma 1 — 953,2 MiB.
В сумме это около 1 773 MiB, или 1,73 GiB памяти без учёта MySQL.
Новый application container в сопоставимом снимке занимал 178,2 MiB.
То есть потребление памяти application layer уменьшилось примерно на 90%, практически в 10 раз.
Любопытная деталь: один только контейнер Prisma 1 старого стека использовал более чем в пять раз больше памяти, чем всё новое приложение.
Это хороший пример того, почему HAIH интересуется не количеством зависимостей само по себе и не эстетикой архитектурной диаграммы. Важнее измеримые свойства системы: сколько времени потребовалось для capability, насколько легко результат проверить, сколько ресурсов он требует и насколько сложно будет изменить решение дальше.
AI здесь был не генератором проекта
Есть соблазн описывать подобные истории как «AI написал новый сайт». Но такое описание скрывает самую важную часть работы.
Основная ценность агента проявилась не в способности быстро напечатать React-компоненты или SQL. Современные модели и без HAIH достаточно хорошо знают популярные библиотеки.
Гораздо интереснее другое: агенту приходилось исследовать существующую систему, сопоставлять данные и старые URL, проверять гипотезы, находить противоречия, менять архитектурное решение после появления новых фактов и оставлять проверяемые результаты.
Именно здесь начинает работать идея инженерной памяти.
Следующему агенту не так важно получить ещё один шаблон Express + React Router + GraphQL. Такой код он способен собрать заново.
Гораздо ценнее знать:
- почему первоначальная идея сохранить legacy-модель оказалась не лучшей границей;
- какие свойства старого web-контракта пришлось сохранять;
- где исторические данные не совпадают с современной предметной моделью;
- какие компромиссы были приняты;
- какими тестами подтверждалась совместимость;
- какие измерения были получены после production deployment;
- что осталось неизвестным или сознательно отложенным.
Это и есть тот слой знаний, который HAIH пытается сделать переносимым между задачами.
Greenfield и brownfield оказались зеркальными задачами
Первые эксперименты HAIH были greenfield-сценариями.
Начинаем с маленького сайта. Появляется новое требование — добавляем ровно столько архитектуры, сколько нужно. Понадобился server logic и API — появился единый сервер и GraphQL. Не нужна база — не добавляем базу просто потому, что «так принято».
Пивная карта проверила тот же принцип с противоположной стороны.
Здесь архитектуры изначально было слишком много — несколько поколений технологий и годы накопленных решений. Поэтому движение шло не от нуля вверх, а от сложной legacy-системы вниз к реальным требованиям.
В обоих случаях принцип один:
Архитектура — следствие доказанных требований, а не стартовая точка проекта.
В greenfield это защищает от преждевременного усложнения.
В brownfield — от автоматического переноса исторической сложности в новую системуу.
Что изменилось в самой методике
Этот проект оказался полезен и для HAIH как эксперимента.
Стало очевидно, что для brownfield недостаточно хранить только решения о новом коде. Нужен отдельный слой знаний о совместимости: legacy capabilities, data mapping, URL contracts, migration rules и verification artifacts.
Кроме того, production заставляет гораздо строже относиться к слову «проверено». Сохранённый crawl, Lighthouse report, docker stats, тест или список URL — это evidence только для определённого состояния системы и определённых условий проверки.
Поэтому хороший инженерный журнал должен отвечать не только на вопрос «что получилось?», но и на вопросы «когда?», «на какой версии?», «как проверяли?» и «что эта проверка не доказывает?».
Это, пожалуй, один из наиболее ценных результатов практического применения подхода.
Результат как начало следующего эксперимента
Версия 1.0.0 уже оформлена отдельным релизом pivkarta.ru-3. Сам результат можно посмотреть на pivkarta.ru.
Релиз важен не как заявление о том, что продукт теперь навсегда закончен. Напротив: дальнейший редизайн внутренних страниц, write-сценарии и другие возможности будут развиваться отдельными задачами.
Но граница текущего эксперимента достигнута: старый публичный сайт получил production replacement, основные данные и web-контракт сохранены, а новая система оказалась заметно легче и быстрее измеряемого legacy runtime.
Для HAIH это первый серьёзный brownfield-кейс и хороший ответ на вопрос, с которого начиналась вся идея.
AI-агенту действительно не обязательно давать ещё один большой фреймворк, пытающийся заранее решить все будущие задачи. Возможно, полезнее дать ему накопленный инженерный опыт, научить начинать с требований, проверять решения на реальной системе и сохранять evidence так, чтобы следующий эксперимент начинался не с нуля.
Пивная карта показала, что этот подход работает не только на демонстрационном проекте. Он пережил встречу с 250 legacy-таблицами, десятками тысяч исторических URL, реальными данными и production deployment.
А это уже гораздо более интересная проверка гипотезы.