Симптом в день переключения простой: новый путь готов, но никто не называет условие, при котором его надо остановить. В chat появляются предложения «включим на десять процентов» и «если что, откатим». Ни доля, ни слово rollback не объясняют, какой traffic затронут, какие сигналы сравнят, кто может остановить волну и что случится с данными. Цена — широкий blast radius и спор после факта: команда не знает, проблема в новой реализации, общей зависимости или способе измерения.
Rollout для legacy-модернизации начинается не с процента. Он начинается с decision gate: до какого действия разрешён current evidence, какой owner отвечает за следующий переход и какое обратимое действие доступно. В первой стадии может быть только legacy-only route и review шва. Во второй — предложение ограниченного нового пути, но не автоматическое включение. В третьей — расширение после отдельно зафиксированного evidence. Это медленнее одного toggle, но дешевле, чем воспринимать production как инструмент обнаружения неизвестных правил.
Gate отвечает на один вопрос и не выдаёт себе чужую власть
У каждого gate есть объект проверки. Gate совместимости спрашивает, определены ли cases и evidence. Gate доставки спрашивает, какая версия adapters и routing rule попадёт в контур. Gate наблюдения спрашивает, какие признаки можно сравнить между control и новой частью. Gate rollback спрашивает, что реально вернуть одним обратимым действием. Нельзя склеить их в один status green: тогда непонятно, проверено ли поведение, сборка или доступ к кнопке возврата. Любой gate может сказать unknown; это результат, а не ошибка отчёта.
Google SRE Workbook 2018 определяет canary как частичное и ограниченное по времени развёртывание с оценкой, которая помогает решить, продолжать ли rollout. В главе есть техническая деталь: canary signals нужно сопоставлять с control signals, а окно метрики не должно размывать короткую волну. Для нас это не формула «выберите 5 процентов». Это дисциплина: до числа процентов назвать population, control, duration, signal, source и owner. Если хотя бы один пункт неизвестен, процент станет декорацией и не защитит от ложного вывода.
| Gate | Что проверяется | Решение при PASS | Чего PASS не доказывает |
|---|---|---|---|
| Seam review | one route, owner, old/new boundary | подготовить contract | что legacy уже понятно целиком |
| Compatibility review | valid/invalid/repeat cases и evidence plan | разрешить ограниченный proposal | реальное parity без запуска |
| Delivery review | версия adapter и rule маршрута | согласовать окно изменения | отсутствие внешней деградации |
| Observation review | control, population, duration и signal source | выбрать manual decision после волны | причину любого расхождения |
| Rollback review | return route и data boundary | разрешить обратимое изменение | восстановление необратимых данных |
Ограниченная волна имеет смысл только рядом с control
Просто отправить часть запросов в новый adapter недостаточно. Нужна сопоставимость: тот же тип request, известная population boundary и signal, чей смысл не меняется между путями. Если новый путь получает только пользователей без скидок, а legacy — остальных, разница может описывать population, не implementation. Если duration меньше окна агрегации, старые ошибки могут попасть в вывод о новом пути. Google разбирает такую ошибку с короткой canary-волной и часовым aggregation. В реальном plan это повод записать окно и источник signal рядом с решением, а не угадывать после alert.
Для stateful операций control особенно коварен. Cache, affinity, retry и shared database могут связать старый и новый путь. Synthetic load помогает проверить code branch, но не обязательно представляет state coverage; Google отдельно предупреждает об этом ограничении. Поэтому нельзя заявлять: новый путь прошёл synthetic traffic, значит он безопасен. Умнее ограничить первый шов до операции, в которой state boundary наблюдаема, или оставить stateful effect на legacy до появления data plan. Без этого rollout может создать состояние, которое нельзя честно откатить.
Rollback-route и восстановление данных — разные работы
Rollback-route отвечает на один вопрос: как направить следующий допустимый запрос обратно в legacy-only path. Это может быть версия routing configuration, proxy rule или выключение выделенного adapter. Он должен иметь owner, known prior state и подтверждение, что правило вернулось. Data recovery отвечает на другой вопрос: как поступить с уже созданными или изменёнными данными. Иногда он невозможен без reconciliation. Называть первое вторым опасно: route может вернуться за минуты, а созданное событие или изменённый баланс останется и потребует business decision.
Перед rollout стоит спросить пять раздельных вещей: что возвращаем, кто делает действие, какие новые requests перестанут идти в новый путь, какие записи уже не отменяются и как будет видно, что маршрут вернулся. Если ответа нет, plan честно записывает rollback unavailable for data. Это может блокировать волну или требовать другого scope, но не является поводом добавить delete-script. Обратимость — свойство конкретного действия, не обещание команды. M7-тон нужен, чтобы назвать цену необратимости до того, как она станет пользовательской.
Существует отдельная граница для внешнего provider. Даже если route возвращён, запрос мог уже уйти в payment gateway, email service или partner API. Для такого effect нужен record id, reconciliation owner и правило общения с business. Нельзя проверить это переключением маршрута. Если данная операция входит в первый шов, gate обязан прямо признать, что rollback-route не покрывает provider effect. Часто безопаснее начать с preview или read model, чем добывать мнимую обратимость через агрессивную компенсацию.
Не отдавайте решение fixture или CI-иконке
Учебный fixture хранит synthetic stages: legacy-only, limited-new-path-proposed и expand-after-owner-approval. У всех state равно not-executed; у rollout releaseAuthority равно not-granted. Код отвергает попытку переставить stages, назвать automatic release, удалить legacy-data в rollback или записать coverage как измеренный факт. Поэтому fixture подходит как машинная проверка, что decision record не потерял ручную границу. Он не умеет включить route, сравнить metrics, прочитать deployment history или сказать, что user traffic обработан корректно.
node web/scripts/upgrade-2024-01.mjs --verify-fixture
У fixture нет I/O: он не читает legacy code/history, не запускает parity tests, CI, сеть или HTTP, не измеряет coverage/performance и не создаёт records вне памяти процесса. Synthetic names помечены намеренно. PASS не означает, что canary готов, monitoring достаточен или real rollback работает. Он означает, что plan не перепутал выбор человека с execution системы и не выдал route proposal за data recovery. Это небольшой технический барьер против ложной уверенности в документах rollout.
Маршрут: симптом → причина → проверка → действие
- Симптом. Команда предлагает процент rollout, но не называет control, duration, source сигнала и условие остановки.
- Причина. Процент приняли за стратегию, а rollback-route смешали с восстановлением данных. Gate не владеют вопросами, поэтому каждый status выглядит одинаково зелёным.
- Проверка подготовленности. Для шва выпишите owner, version, population, control, duration, signal, decision rule и rollback-route. Отсутствующее значение остаётся unknown.
- Проверка данных. Отдельно назовите immutable или append-only effects и того, кто решает reconciliation. Не объявляйте их автоматически восстановимыми.
- Действие. Разрешите только волну, для которой можно вернуться к known legacy route без необъявленного изменения данных; остальной scope остаётся legacy-only.
- Повтор. После волны owner сравнивает выбранные evidence и выбирает expand, pause или return. Новый signal без control открывает расследование, не автоматический вывод.
Небольшой rollout не равен маленькому риску
Даже одна операция имеет большой impact, если запускает платёж, уведомление, доступ или перезапись общей записи. Тогда правильный первый шаг — не процент traffic, а более узкий contract: read-only preview, отдельный tenant с соглашением или staging с представительным состоянием. Если таких условий нет, команде не обязательно делать canary ради ритуала. Можно оставить legacy path, подготовить evidence и вернуться к migration позже. Отложенный rollout с ясной причиной дешевле быстрого rollout с необъяснимым effect.
Есть и противоположный риск: остановить модернизацию навсегда, потому что идеальный safety case недостижим. Выход — не отменять требования, а делить их по месту. Route return проверяем до rollout. Contract cases — на test контуре. Data reconciliation — отдельная работа с owner. Observability — checklist с доступом к реальным данным. Когда эти части названы, команда выбирает первый обратимый шаг и его цену. Необязательно знать всё о монолите, чтобы честно не трогать то, что нельзя контролировать.
Ограничения и следующий шаг
В статье нет настоящего pipeline, feature flag, traffic split, dashboard, latency, error rate, production population или исполнения rollback. Она не назначает универсальные проценты и не обещает, что canary заменяет testing. Google Workbook описывает принципы и ограничения; Fowler говорит о риске cut-over; OAS описывает форму interface. Эти источники не знают вашу модель данных, policy доступа, допустимый impact или договор с consumer. Реальная волна требует собственных owners, прав и evidence.
Следующий шаг: заполните одну gate-card до изменения. В ней должны быть seam id, версия adapter/rule, owner, population/control, duration, signal source, decision rule, rollback-route и data boundary. Проведите tabletop-review без включения traffic: кто может сделать return, что он изменит и чего не изменит. Если карточка не даёт ответ, уменьшите scope. Такой результат полезнее запуска rollout по дате. Он сохраняет возможность развивать legacy без выдуманного обещания, что всё поведение уже известно.
Историческая граница января 2024
Все источники существовали до конца января 2024: Fowler — с 2004 года, OAS 3.1.0 — с 2021-го, Google SRE Workbook — из издания 2018 года. Материал не подтягивает поздние инструменты и не сочиняет production rollout. M7 проявляется в цене сосуществования, владельце решения и отделении обратимого route change от данных; это развитие инженерного автора, не декларация безрисковой миграции.
Проверяемые источники
- Martin Fowler: Original Strangler Fig Application, 29.06.2004 — Первичный текст автора метафоры: критическое cut-over переписывание оказывается сложнее ожидаемого и рискованно; постепенное вытеснение может раньше дать ценность. Это не готовая инструкция для чужого домена, базы данных или маршрутизатора.
- OpenAPI Specification v3.1.0, 15.02.2021 — Официальная спецификация описывает language-agnostic интерфейс HTTP API, paths, operations и Schema Object. Она помогает фиксировать форму интерфейса, но не доказывает runtime parity, порядок эффектов или поведение неизвестного legacy-модуля.
- Google SRE Workbook: Canarying Releases, copyright 2018 — Официальная глава определяет canary как частичное и ограниченное по времени развёртывание с оценкой перед продолжением, требует сравнивать canary и control и называет границы synthetic load. Она не задаёт процент, метрики, полномочия или rollback для этого пакета.