Фронт деплоится за 3 минуты, бэк — за 40: как мы это решали в headless-проекте
Мы перешли на headless. Фронт стал деплоиться за 3 минуты. Бэк — нет.
Первые два месяца мы жили в режиме: фича в Next.js готова, а Bitrix API ещё нет. Или наоборот — бэк обновился, фронт не знает об этом. Продакшн вроде бы зелёный, а сайт не работает как надо. Это не баг архитектуры headless. Это управленческая задача, о которой почти никто не пишет.
В headless деплой — не одна операция, а две
В монолите у вас один репозиторий, один деплой, одна точка синхронизации. Фронт и бэк выходят вместе. Это неудобно, но хотя бы предсказуемо.
В headless у вас два независимых стека с разной скоростью доставки кода в продакшн. Теоретически это свобода. На практике — асимметрия, которую надо уметь контролировать.
Next.js за 3 минуты, Bitrix за 40: что под капотом
Наш стек: IvanPin/ivanpin.com работает на Next.js + PM2 на том же сервере. Деплой — это git pull, npm run build, pm2 restart. Обычно 2–3 минуты. Если что-то сломалось — откатили предыдущий pm2 снапшот за секунды.
Бэкенд IvanPin/wgp_backend — это Bitrix. Деплой PHP-эндпоинтов идёт через FTP (скрипт deploy_ivanpin_api.py). Последовательность: заливка файлов, сброс OPcache через HTTP-вызов на проде, проверка что эндпоинты отвечают. Реалистичное время с переключением контекста и ручными проверками — 30–40 минут.
Разрыв 10–13x. Это не трагедия, если вы управляете им сознательно.
Три паттерна рассинхрона, которые убивают итерации
- Фича в Next.js готова, тесты проходят. Вы деплоите фронт — и пользователи видят пустое место, потому что бэк ещё не знает об этом поле в API. Если вы не держите совместимость в API по умолчанию, этот паттерн будет повторяться снова и снова.
- Вы обновляете формат ответа в Bitrix-эндпоинте. В тестовой среде всё хорошо. На проде Next.js начинает получать другой JSON и тихо ломается — без 500-ки, просто данные отображаются не так. Вы узнаёте об этом через несколько часов.
- Самый болезненный для нашего конкретного стека:
wgp_backendобслуживает одновременноivanpin.comиwebgoodpeople.com. Изменение API для одного сайта может задеть второй. Деплой бэка — не изолированная операция, а риск для нескольких потребителей сразу.
API-контракты как способ развязать стеки
Первое, что помогло — это зафиксировать контракт. У нас есть X-WGP-Token и фиксированный набор эндпоинтов в /api/ivanpin/services/. Это уже зачаток контракта: Next.js знает, что будет в ответе, а Bitrix знает, какой формат не менять.
Практическое правило, которое мы ввели: никакие сломанные изменения API не деплоятся без одновременного обновления фронта. Если изменение не обратно совместимо — вводим версионирование или промежуточный адаптер на стороне Next.js.
Это не сложная архитектура. Это договорённость, которую надо сделать явной.
Feature-флаги: где держать состояние
Следующий вопрос: вы добавляете новую фичу. Когда её «включать» — на стороне фронта или бэка?
Мы разделили это так: если фича зависит от данных бэка — флаг на стороне бэка. Это может быть поле в API-ответе (feature_enabled: true/false), или просто отсутствие/наличие endpoint'а в /api/. Next.js проверяет перед рендером. Если бэк не готов — фича не показывается.
Если фича чисто фронтовая (UI, переключение компонента) — флаг в Next.js, в переменных среды или в конфиге. Деплоится без участия Bitrix.
Это разделение убрало большую часть проблем рассинхрона для нас.
Что мы поменяли в процессе деплоя
Раньше деплой бэка был: «сейчас возьму и обновлю». Теперь — чеклист из 4 шагов:
Первое — проверяю, есть ли на фронте незадеплоенные изменения, которые ждут этого бэк-апдейта. Если есть, деплою пакетом.
Второе — для любого изменения API проверяю обратную совместимость. Если ломаю формат — обновляю фронт первым.
Третье — после деплоя Bitrix прогоняю смоук-тест на обоих сайтах. Один HTTP-запрос к /api/ivanpin/services/blog/ и один к /api/services/wgp/ — убеждаюсь, что оба отвечают корректно.
Четвёртое — фиксирую в deploy_ivanpin_api.py какие именно файлы были изменены. Это позволяет откатиться к предыдущей версии за 5 минут, если что-то пошло не так.
Что не работает
Я не автоматизировал деплой Bitrix и не буду это делать ближайшее время. Причина проста: бэк живёт на общем сервере с несколькими проектами, ошибка в автоматическом деплое может задеть продакшн клиентского проекта. Ручной деплой с чеклистом дороже по времени, но дешевле по рискам.
Это не оправдание. Это осознанный выбор в пользу надёжности.
Итог
Переход на headless не решает проблему деплоя — он её переформулирует. Вместо «мы деплоимся вместе» вы получаете «мы деплоимся независимо, но должны координироваться».
Если ваш Next.js уходит в прод за 3 минуты, а Bitrix — за 40, это не повод отказываться от headless. Это повод выработать правила: что деплоится первым, где живут флаги, как вы проверяете совместимость.
Управляемая асимметрия лучше, чем кажущаяся синхронность.
→ Подробнее о том, почему я выбрал headless именно для этого проекта — в статье Headless — это не про скорость. Это про то, чтобы Bitrix не ронял фронт.
→ Как я принимал решение отказаться от переписывания Bitrix — Я отказался от $40K-контракта, чтобы не переписывать Bitrix