Feature Flags: рубильники безопасности для продакшена

Представьте пульт звукорежиссёра на большом концерте. У каждого инструмента свой фейдер. Барабаны звучат слишком громко? Просто опускаете один ползунок, не выключая всю систему. Вокал пропал на припеве? Поднимаете и порядок. Никто не перепаивает провода между песнями.

Feature flags (они же feature toggles, флаги функций) это те же самые фейдеры, только для кода. Вы включаете или выключаете функциональность без нового деплоя, без перезапуска серверов, без лишнего риска.

В главе «Уменьшение рисков» мы уже коротко касались этой темы на примере выключателя света. Теперь давайте посмотрим на флаги с точки зрения SRE — как на полноценный инструмент управления надёжностью.

Kill Switch: экстренное отключение без деплоя

Самое главное, что должен давать feature flag — возможность экстренно отключить проблемную функциональность за секунды. Не за минуту, не за час деплоя, а за время, которое нужно, чтобы переключить конфиг.

Когда в 2012 году Knight Capital рухнула за 45 минут, потеряв 440 миллионов долларов, у них не было такого рубильника. Новый код поехал на все серверы разом, откатить быстро не смогли — и всё. В главе «Надежных систем не бывает» мы говорили о том, что kill switch — один из базовых принципов контролируемости системы. Feature flags — это и есть те самые рубильники.

Как это выглядит на практике:

  1. Код новой фичи выкатывается на продакшен, но флаг по умолчанию выключен.
  2. Если после включения флага что-то пошло не так, вы его просто выключаете.
  3. Система мгновенно возвращается к старому поведению без отката деплоя.

Разница между откатом деплоя (rollback) и выключением флага — это разница между эвакуацией целого здания и выключением одного кондиционера, который дымит.

В иммутабельной инфраструктуре откат — это развёртывание предыдущей версии, что может занять 10-15 минут. Флаг срабатывает за секунды. Это не замена rollback'у, а первая линия обороны.

Постепенная раскатка: от 1% до 100%

Безопасность флагов раскрывается в полную силу, когда мы используем их для постепенного увеличения аудитории новой фичи.

Никто в здравом уме не включает новую функциональность сразу всем пользователям. SRE-подход — катить маленькими шагами и на каждом шаге проверять, не нарушаем ли мы SLO:

  1. 1% пользователей — «tech preview». Проверяем, что код не падает, метрики зелёные, ошибок нет.
  2. 5% — расширяем аудиторию. Смотрим на SLO сервиса: не просела ли латентность? Не выросла ли ошибка 5xx?
  3. 25% — уже серьёзная нагрузка. Если на этом этапе всё стабильно, можно быть уверенным, что фича не развалит систему.
  4. 100% — полный релиз. Но флаг остаётся в коде на случай, если проблема проявится не сразу (а такое бывает).

На каждом шаге мы смотрим на дашборды, проверяем error budget и решаем: катимся дальше или стоп. Делаем паузу между шагами, чтобы дать системе «устаканиться» и собрать статистику.

Canary-релизы: ещё один слой безопасности

Feature flags тесно связаны с canary-релизами (подробно — в главе «Canary и Progressive Delivery»). Canary — это когда новый код сначала получает маленький кусочек трафика, а потом, если всё хорошо, — весь остальной.

Связка работает так:

  • Canary-инстансы крутят новую версию кода с включённым флагом новой фичи.
  • Если canary начинает деградировать, мы не просто отзываем canary-инстансы — мы выключаем флаг и для них.
  • Это двойная защита: сбой может быть и в новом коде, и в новом поведении.

A/B-тестирование и платформа экспериментов

Feature flags — это не только про безопасность, но и про бизнес. Хотите проверить, повысит ли зелёная кнопка конверсию? Заворачиваете обе версии во флаги, включаете каждой по 50% аудитории, меряете метрики.

Только здесь есть нюанс: A/B-тесты требуют, чтобы флаг был стабильным для конкретного пользователя (один и тот же user_id всегда видит одну и ту же версию). Для этого флаги привязывают к идентификаторам пользователей, а не включают рандомно. Иначе вы никогда не поймёте, что на что повлияло.

Технический долг флагов: flag spaghetti

У флагов есть тёмная сторона. Чем больше флагов в коде, тем сложнее в нём разбираться:

  • Код обрастает if-ами на каждый чих. Прочитать такой код без бутылки сложно.
  • Флаги копятся годами. В большой системе можно найти флаги, которые включали и забыли, фича уже всем доступна год, а if висит.
  • Если один флаг влияет на работу другого — вы получаете «flag spaghetti», где предсказать поведение системы невозможно.

Правило простое: жить флагу не больше двух недель после полного включения. Завели флаг, раскатали фичу на 100%, через две недели — удалили старый код и сам флаг. Навсегда.

Совет

Заведите в коде линтер, который находит включённые флаги старше N дней и шлёт уведомления в тимчаты. Или ещё лучше — автоматически создаёт задачи на удаление. Если через месяц флаг всё ещё в коде — значит, процесс сломан.

Интеграция с Error Budget

Самая крутая штука — связать feature flags с error budget'ом (см. главу «SLO как код»).

Идея простая: у сервиса есть бюджет ошибок — сколько «девятик» доступности мы готовы потратить на эксперименты. Если бюджет ошибок зелёный, мы можем позволить себе включить risky-фичу на 10% пользователей. Если бюджет ошибок на нуле — никаких экспериментов, только багфиксы.

Вот как это выглядит в CI/CD:

- name: "Проверить Error Budget"
  run: |
    budget=$(curl -s slo-service/api/v1/budget/my-service)
    if [ "$budget" = "exhausted" ]; then
      echo "Error budget исчерпан. Фича не включается."
      exit 1
    fi

Автоматика может даже сама отключать флаги, если после их включения начал быстро сжигаться бюджет ошибок. Это называется auto-remediation. Система заметила аномалию — выключила флаг — отправила уведомление — инженер разбирается уже без пожара.

Итог

Feature flags — это не про «быстрее выкатывать фичи» (хотя это тоже). Это про контроль и безопасность. Возможность сказать: «Мы залили код, но он не активен. Мы включим его аккуратно, маленькими шагами. Если что-то пойдёт не так — мы выключим его быстрее, чем пользователи заметят проблему».

В сочетании с SLO, error budget'ами и canary-релизами feature flags превращают развёртывание из лотереи в предсказуемый, управляемый процесс. И это именно то, чем SRE отличается от «просто DevOps».