Отката нет — значит выкат не готов
Выкат считается готовым, когда написан не только путь вперёд, но и путь назад. Звучит очевидно, а на практике план отката появляется в двух состояниях: либо его нет вовсе, либо он существует в виде фразы «ну откатим коммит».
Разберу, почему второе — это отсутствие плана, и как выглядит настоящий.
Три вопроса, на которые отвечает откат
Любой план отката отвечает на три вещи. Если хоть одна не проговорена — плана нет.
Что конкретно выполнить. Не «вернуть предыдущую версию», а команды, которые дежурный выполнит в три ночи, не разбираясь в архитектуре.
Сколько это займёт. Пять минут и сорок минут — принципиально разные решения. От этой цифры зависит, откатываться или чинить на месте.
Что при этом потеряется. Самый пропускаемый пункт. Откат почти никогда не бесплатен: теряются данные за период, ломаются уже отданные наружу ссылки, отменяются транзакции.
Оформляется это коротко:
## Откат
<команды>
Время: ~5 минут.
Теряется: транзакции за период между бэкапом и откатом.
Три строки. Их отсутствие превращает аварию в импровизацию.
Почему «откатим коммит» — это не откат
Revert возвращает код. Он не возвращает:
- схему базы, если миграция была необратимой;
- данные, которые новая версия успела записать в новом формате;
- состояние внешних систем — отправленные вебхуки, созданные подписки, проведённые платежи;
- кэши и индексы, собранные под новую версию.
Для статического сайта revert действительно почти достаточен — там нет состояния. Как только появляется база и внешние интеграции, «откатим коммит» становится опасной иллюзией: код вернулся, а данные остались в форме, которую старый код прочитать не может.
Отсюда практическое следствие: необратимая миграция должна быть помечена как необратимая, и это меняет план выката целиком — вместо отката там появляется починка вперёд, и её тоже нужно описать заранее.
Выкат, который нельзя откатить, тоже бывает
Иногда отката нет объективно: разослано письмо, опубликован пост, проведён платёж. Это нормально. Ненормально — узнать об этом в момент, когда откат понадобился.
Такие шаги выносятся в отдельный список «точки невозврата» с явным указанием, после какого действия обратной дороги нет. Дальше решение принимается осознанно: либо ставим ручное подтверждение перед этим шагом, либо принимаем риск.
Что проверяется до выката, а не после
Короткий чек-лист, который стоит держать в runbook:
- Команды отката записаны и понятны без автора
- Время выполнения отката известно
- Что теряется при откате — написано явно
- Бэкап снят перед выкатом, а не по расписанию «где-то ночью»
- Восстановление из этого бэкапа когда-нибудь проверялось, дата известна
- Необратимые шаги помечены, для них описана починка вперёд
Последний пункт про бэкап стоит отдельного внимания: бэкап, из которого ни разу не восстанавливались, — это предположение. Проверенный restore с датой проверки превращает его в факт. Разница обнаруживается в худший возможный момент.
Откуда это правило растёт
Из наблюдения, что авария — плохое время для проектирования. В момент, когда прод лежит, человек не изобретает процедуру: он выполняет ту, что написана, либо импровизирует под давлением. Второе даёт вторую аварию поверх первой — и обычно она дороже исходной.
Пять минут на три строчки плана отката покупают возможность действовать по инструкции вместо того, чтобы принимать решения на адреналине.