Новогодняя заморозка изменений: когда перестать деплоить
Тридцать первого декабря сломался деплой, который выкатили тридцатого — обычная фича, ничего критичного, просто чуть поменяли логику расчёта скидки в корзине. Команда уже разъехалась по родственникам, дежурный один, эскалировать некому, а клиенты пишут в поддержку, что суммы в заказах не сходятся. Это не гипотетический сценарий, а типичная причина, по которой у зрелых команд перед длинными праздниками появляется формальная заморозка изменений — период, когда прод трогают только по крайней необходимости.
Содержание
Зачем вообще нужна заморозка
Дело не в суеверии «не деплоить перед праздниками», а в математике риска. Обычный деплой в будний день имеет предсказуемый путь отката: если что-то пошло не так, откатывающий инженер рядом, дежурный на связи, а решение по эскалации принимается за минуты. В новогодние праздники этот путь рвётся в нескольких точках сразу: часть команды физически недоступна, время реакции на алерт растёт, вторая линия поддержки может вообще не работать, а клиенты в это время наоборот активны — распродажи, подарки, бронирования на каникулы.
Заморозка не устраняет риск деплоя — она устраняет риск деплоя в момент, когда стоимость ошибки максимальна, а ресурсы на её исправление минимальны. Смысл не «ничего не трогать месяц», а сознательно сократить количество изменений в проде до тех, что действительно нужны, именно в те даты, когда цена простоя и скорость восстановления расходятся сильнее всего. Это тот же принцип, что и с ростом цены простоя на пике сезонной нагрузки — только здесь пик совпадает с падением доступности команды, а не только с ростом трафика.
Важно сразу разграничить: заморозка кода — это не заморозка проекта целиком и не консервация инфраструктуры на время простоя. Серверы работают, мониторинг работает, дежурство продолжается — просто поток изменений в прод сокращается до минимума.
Когда начинать: считайте от даты, а не от настроения
Частая ошибка — объявлять заморозку «на всякий случай» слишком рано, из-за чего команда либо игнорирует правило, либо копит невыкаченные изменения в один опасный релиз перед стартом заморозки. Разумнее считать дату старта от трёх факторов, а не назначать её волюнтаристски.
Фактор 1 — дата фактического снижения доступности команды. Если официальные праздники с 1 по 8 января, но половина команды уходит в отпуск с 28 декабря, а вторая половина работает не в полную силу с 27-го — заморозка должна начаться не позже 26–27 декабря, иначе последний рабочий день превращается в «успеть впихнуть всё перед закрытием» с максимальной вероятностью ошибки.
Фактор 2 — время на стабилизацию последнего релиза. Между последним «обычным» деплоем и стартом заморозки должно быть время, чтобы отловить регрессии в спокойном режиме — обычно это 2–3 рабочих дня с полной командой на месте. Если релиз выкатили в пятницу перед заморозкой в понедельник, у вас не было ни одного дня на проверку — это уже не подготовка, а тот же риск, что вы пытались избежать.
Фактор 3 — длина самой заморозки. Чем длиннее период недоступности команды, тем раньше нужно закрыть окно изменений, потому что даже мелкий баг, пропущенный в тестах, успевает докатиться до пользователей и накопить последствия за счёт объёма трафика в праздники.
Практический ориентир, который используют многие команды: заморозка длится с последнего рабочего дня перед длинными праздниками до первого полноценного рабочего дня после них, а окно «только критика» открывается на 3–5 рабочих дней раньше — чтобы успеть стабилизировать последний плановый релиз. Конкретные даты у вас будут свои — зависят от календаря, состава команды и от того, насколько активен у вас трафик именно в праздники (для интернет-магазина и для B2B SaaS логика может отличаться на неделю).
Зафиксируйте даты письменно и заранее — не «где-то в районе праздников», а конкретные числа в календаре команды, в Slack-канале и в README репозитория. Расплывчатая формулировка гарантированно приведёт к спору 29 декабря о том, распространяется ли заморозка на «мелкий фикс верстки».
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверЧто считается критичным исключением
Заморозка бессмысленна без чёткого списка того, что можно выкатывать даже во время неё — иначе либо всё превращается в исключение, либо команда молча нарушает правило при первом неудобстве. Разумный список исключений обычно выглядит так.
| Категория | Пример | Проходит без обсуждения? |
|---|---|---|
| Security-патч с активной эксплуатацией | Закрытие CVE, по которому уже фиксируются попытки эксплуатации | Да, немедленно |
| Security-патч без признаков эксплуатации | Плановое обновление зависимости с уязвимостью | Нет — оценка риска, обычно можно подождать |
| Утечка данных / потеря денег клиентов | Баг в расчёте платежей, дублирование списаний | Да, с эскалацией на ответственного |
| Полная недоступность сервиса | 5xx на всех запросах, сервис не отвечает | Да, это уже инцидент, а не деплой |
| Деградация без полного отказа | Медленный ответ у части эндпоинтов | Нет — обычно чинится конфигурацией/масштабированием, не деплоем нового кода |
| Косметический баг | Съехала вёрстка, неправильный текст | Нет, ждёт окончания заморозки |
| Фича, которую «очень просили» | Новый отчёт для одного клиента | Нет, ни при каких условиях |
Ключевой критерий — не «насколько это важно для бизнеса», а «продолжает ли ущерб нарастать прямо сейчас, и можно ли его остановить только деплоем кода». Если проблему можно снять фича-флагом или откатом конфигурации без выкатки нового кода — это почти всегда безопаснее полноценного деплоя в заморозку.
Отдельно распишите security-исключение — именно здесь чаще всего происходит путаница. Не любая уязвимость повод ломать заморозку: если план реагирования на инцидент безопасности у вас уже есть, используйте его критерии серьёзности, а не решайте на глаз в новогоднюю ночь. Плановое обновление пакета с CVE низкой критичности без свидетельств эксплуатации ждёт окончания заморозки; RCE в интернет-доступном сервисе, который уже сканируют — нет.
Как коммуницировать заморозку команде
Заморозка, о которой знает только тимлид, не работает. Минимальный набор коммуникации:
- Календарное событие на весь период заморозки, с точными датами старта и конца, видимое всей команде, а не только инженерам — продукт и поддержка тоже должны знать, почему их «маленькую правку» не выкатят завтра.
- Закреплённое сообщение в общем канале за 1–2 недели до старта, с ссылкой на регламент: кто принимает решение по исключениям, куда писать, если кажется, что нужен экстренный деплой.
- Технический барьер, а не только договорённость на словах. Устная договорённость забывается 30 декабря в 18:00. Технически заморозку стоит закрепить:
# .gitlab-ci.yml — пример гварда деплоя по переменной
deploy_prod:
stage: deploy
script:
- ./deploy.sh production
rules:
- if: '$CI_PIPELINE_SOURCE == "web" && $FORCE_DEPLOY == "true"'
when: manual
- if: '$FREEZE_ACTIVE == "true"'
when: never
- when: on_success
Переменную FREEZE_ACTIVE выставляете в настройках проекта на даты заморозки и снимаете вручную после её окончания — это дешевле, чем полагаться на память дежурного. В GitHub Actions то же самое можно сделать через защиту окружения (environment protection rules) с ручным approval на конкретный environment: production, который на время заморозки переключаете на «требует approval от двух человек из отдельного списка».
- Список ответственных за исключения. Один-два человека (тимлид + technical lead, например), которые физически на связи весь период и имеют право утвердить экстренный деплой. Без этого решение «можно ли выкатывать» будет приниматься тем, кто оказался онлайн — не всегда с нужным контекстом.
- Ссылка на регламент дежурства. Если у вас команда небольшая, свяжите заморозку с графиком дежурства на праздники — дежурный должен точно знать, кто утверждает исключения и по какому каналу его будить, если решение нужно ночью.
Как коммуницировать заморозку клиентам
Если у вас есть внешние клиенты с собственными релизными циклами, интеграциями через API или зависимостью от ваших плановых обновлений — их тоже нужно предупредить, причём раньше, чем команду внутри.
Что обычно сообщают клиентам:
- Даты, в которые плановые обновления и новые фичи временно не выкатываются (без лишних деталей про внутренний CI).
- Что продолжает работать в обычном режиме: поддержка критичных инцидентов, мониторинг, экстренные security-исправления.
- Контакт для эскалации, если у клиента произошло что-то серьёзное — отдельный от обычной очереди тикетов, с более коротким временем ответа.
- Если у вас есть публичный roadmap или changelog — отметьте, что следующий релиз запланирован после окончания заморозки, чтобы не создавать ощущение, будто разработка остановилась насовсем.
Формулировка важна: «мы приостанавливаем плановые релизы с 27 декабря по 9 января, критичные инциденты обрабатываются в обычном режиме» звучит как процесс, а не как «у нас никого нет на месте» — хотя по факту дежурство в эти дни организовано не хуже, чем обычно.
Если у вас есть статус-страница сервиса, разумно опубликовать на ней баннер на период заморозки с теми же датами — это снимает часть входящих вопросов в поддержку ещё до того, как их зададут.
Уже запланированные релизы: что с ними делать
К моменту объявления заморозки в бэклоге почти всегда есть релизы, которые готовились месяцами и должны были выйти как раз в декабре. С ними стоит поступить по одной из трёх схем.
Схема 1 — сдвинуть релиз раньше заморозки. Если фича готова и протестирована, лучше выкатить её на 1–2 недели раньше запланированного, оставив время на стабилизацию, чем рисковать выкаткой прямо перед закрытием окна. «Почти готово» за три дня до заморозки означает «не готово», а не «давайте попробуем успеть».
Схема 2 — отложить на после заморозки. Для всего, что не готово к безопасной выкатке заранее — самый надёжный вариант: сдвинуть релиз на 2–3 недели дешевле, чем разбирать инцидент 2 января с половиной команды на связи.
Схема 3 — задеплоить код, но держать фичу выключенной. Если инфраструктурные изменения (миграции схемы, новые сервисы) должны попасть в прод до заморозки, а сама фича пользователю пока не нужна — разверните код за фича-флагом в выключенном состоянии. Это позволяет получить пользу от заранее протестированного деплоя (миграция уже прошла и стабилизировалась) без риска включения новой логики в праздники. Включение флага после заморозки — не деплой, а конфигурационное изменение, которое проще отследить и откатить.
Отдельно решите вопрос с миграциями баз данных, которые часто становятся узким местом. Если миграция расширяющая (добавляет колонку, не трогает существующие данные) — её обычно можно провести и до, и во время заморозки с минимальным риском. Если миграция сужающая (удаляет поле, меняет тип) — это классический кандидат на перенос на релиз уже после праздников, а не на выкатку в последний рабочий день перед заморозкой.
Перед последним деплоем года пройдитесь по чек-листу перед крупным релизом — не потому что релиз крупный по объёму кода, а потому что это последний деплой, который команда в полном составе успеет спокойно проверить и, если нужно, откатить в тот же день.
Если всё-таки нужно выкатить в заморозку: план действий
Рано или поздно возникнет ситуация, когда исключение оправдано — критичная уязвимость, потеря данных клиентов, полный отказ сервиса. Заранее прописанный порядок действий экономит время именно тогда, когда его меньше всего.
- Подтверждение, что это действительно исключение. Дежурный или инженер, обнаруживший проблему, связывается с ответственным за исключения, а не принимает решение в одиночку — кроме случаев полной недоступности сервиса, где промедление само по себе вредит.
- Минимально достаточное изменение. Экстренный деплой в заморозку — не время для попутного рефакторинга. Патч должен закрывать ровно ту проблему, ради которой сломали правило, и ничего больше.
- Второй человек в ревью, даже ночью. Если совсем некому — хотя бы самопроверка по чек-листу и явное подтверждение от ответственного за исключения в переписке, чтобы решение было зафиксировано, а не осталось устным.
- Подготовленный откат заранее, а не по факту проблемы. Прежде чем катить, зафиксируйте, что именно нужно сделать для отката — тег предыдущей версии, команда для отката миграции, а не «разберёмся, если что». Загляните в заметки о том, что записывать при каждом деплое для возможности отката — этот минимальный набор данных стоит собирать всегда, но в праздники его отсутствие обходится особенно дорого.
- Усиленное наблюдение после деплоя. Не «выкатили и разошлись», а явное время (например, 30–60 минут) с кем-то, кто следит за метриками и логами этого сервиса, прежде чем считать деплой завершённым.
- Запись в реестр исключений. Каждое нарушение заморозки — с датой, причиной, кто утвердил — фиксируется отдельно. После праздников это материал для ретро: если исключений было много, возможно, критерий «критично» слишком широкий или дата старта заморозки выбрана неудачно.
- Короткое уведомление клиентам, если исключение было заметно снаружи. Не нужен подробный post-mortem в моменте, но фраза «мы выкатили экстренное исправление такого-то числа, сервис работает штатно» снимает тревожность у тех, кто заметил деградацию.
После окончания заморозки стоит явно её закрыть — снять FREEZE_ACTIVE, снять approval-ограничение с окружения, написать в канал, что обычный процесс деплоя возобновлён. Незакрытая формально заморозка имеет свойство незаметно продлеваться на пару недель просто потому, что никто не отменил барьер.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Нужна ли заморозка маленькой команде из двух-трёх человек?
Да, и даже больше, чем крупной — там меньше избыточности: если единственный человек, способный откатить прод, в отпуске, любая проблема решается дольше. Формальность может быть минимальной, но принцип «сокращаем изменения перед периодом низкой доступности» работает при любом размере команды.
Что делать с автоматическими обновлениями зависимостей на время заморозки?
Приостановите автослияние PR от Dependabot/Renovate на период заморозки — пусть накапливаются, мержите пачкой после возобновления обычного процесса. Исключение — автоматические security-обновления с высокой критичностью, они идут через тот же процесс, что и ручные security-патчи.
Как быть, если инфраструктурный провайдер тоже проводит работы в этот период?
Уточните заранее регламент технических работ у хостинг- или облачного провайдера на праздничные даты и учитывайте их в графике заморозки отдельно от собственных деплоев — по возможности не накладывайте их на дни без полного дежурства.
Заморозка распространяется на конфигурационные изменения или только на код?
Обычно только на код и миграции. Параметры автоскейлинга, лимиты, DNS-записи — как правило разрешены, потому что откатываются быстрее и реже требуют полноценного деплоя. Но границу стоит проговорить заранее, а не решать по ситуации.
Что, если заморозка совпала с плановым обновлением ОС или патчами безопасности на серверах?
Патчи ядра и критичных пакетов проходят по тому же критерию, что и код — если уязвимость активно эксплуатируется, откладывать нельзя. Обновления без активной угрозы разумно перенести на дату после заморозки.
Стоит ли замораживать сам мониторинг — например, не трогать пороги алертов?
Нет. Пороги на время праздников часто наоборот стоит пересмотреть, потому что паттерн трафика меняется. Замораживать нужно выкатку кода в прод, а не настройку систем, которые помогают этот прод контролировать.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →