Услуги Портфолио Контакты БлогНовости +7 (800) 511‑32‑27 Обсудить проект
Разработка и процессы

Feature flags: как безопасно выпускать новые функции

23 октября 2026·21 мин чтения
Автор материалаЕкатеринаспециалист по процессам YuSMP Group
Добавить YuSMP как предпочитаемый источник в Google
Переключатели функций в продакшене: поэтапный выпуск новых возможностей

Коротко. Feature flag — переключатель в коде, который отделяет деплой от релиза: функция уже на проде, но включается для 1%, 5%, 25% пользователей по кнопке и выключается за секунды без нового деплоя. Флаги снижают риск релизов, ускоряют поставку и дают A/B-тесты. Цена — технический долг: каждый временный флаг нужно удалить после раскатки.

1 августа 2012 года американский брокер Knight Capital за 45 минут после открытия биржи потерял больше 460 млн долларов: по данным Комиссии по ценным бумагам и биржам США (SEC), неудачный деплой нового кода разбудил давно не использовавшуюся дефектную функцию, и автоматика начала отправлять на рынок миллионы ошибочных заявок. Эта история — хрестоматийный пример того, почему feature flags и выпуск функций требуют дисциплины. Канонический разбор того, как флаги устроены и как ими управлять, — статья Пита Ходжсона «Feature Toggles» на сайте Мартина Фаулера, на неё мы будем опираться дальше.

Классический «большой релиз» устроен по принципу «всё или ничего»: новая версия выходит сразу ко всем пользователям, а если что-то пошло не так, единственный способ откатиться — собрать и выкатить предыдущую версию. Поэтому релизы назначают на ночь, команда дежурит, а бизнес ждёт неделями, пока накопится «достаточно» изменений. Feature flags снимают эту боль: код попадает на продакшен заранее и выключенным, а включение превращается в управляемое решение, которое можно принять днём и отменить за секунды. Это один из базовых приёмов, о которых мы рассказывали в статье о DevOps и его пользе для бизнеса.

Ниже разберём, что такое фича-флаги, какие бывают виды, как раскатывать функцию на растущую долю аудитории, какие метрики смотреть, какие инструменты выбрать и как не утонуть в техническом долге. Материал пригодится продактам, техлидам и руководителям, которые хотят выпускать релизы чаще и спокойнее. Мы настраиваем флаги вместе с конвейером поставки в рамках DevOps-сопровождения — поэтому в тексте будет и практика, и типичные ошибки, которые встречаем в проектах.

Что такое feature flags простыми словами

Feature flag (feature toggle, фича-флаг, флаг функциональности) — это условие в коде, которое во время работы приложения решает, показывать пользователю новую функцию или старое поведение, причём значение условия меняется без пересборки и нового деплоя. По сути, это выключатель, вынесенный из кода в настройки: разработчик пишет обе ветки поведения, а какая из них сработает, решает конфигурация.

Простейший пример выглядит так:

if (flags.isEnabled("new_checkout", user)) {
  renderNewCheckout(cart);   // новая корзина
} else {
  renderOldCheckout(cart);   // привычное поведение
}

Функция isEnabled смотрит не только на название флага, но и на пользователя: флаг может быть включён для сотрудников компании, для 5% случайных клиентов или только для жителей одного региона. Благодаря этому одна и та же сборка ведёт себя по-разному для разных людей — и это поведение можно поменять за секунды.

Деплой ≠ релиз. Деплой — техническое событие: новый код оказался на серверах. Релиз — продуктовое событие: пользователи увидели новую функцию. Флаги разводят эти события во времени. Код можно выкатить во вторник, а включить в четверг к началу маркетинговой кампании — и выключить за минуту, если что-то пошло не так.

Разница с обычным релизом хорошо видна в сравнении:

ПараметрОбычный релизРелиз под флагом
Кто видит измененияВсе пользователи сразу после деплояТолько те, для кого включён флаг: команда, бета-группа, процент аудитории
Как откатитьСобрать и выкатить предыдущую версиюВыключить флаг в панели управления
Сколько длится откатОт десятков минут до часов: сборка, тесты, деплойСекунды–минуты, пока клиенты получат новое значение
РискОшибка сразу затрагивает 100% пользователейОшибка затрагивает только включённую долю
Когда включаютВ момент деплоя, часто ночьюКогда удобно бизнесу и команде, в рабочее время

Зачем feature flags бизнесу и команде

Флаги позволяют управлять риском и сроками релизов: выпускать изменения маленькими порциями, проверять их на части аудитории и мгновенно отключать, если что-то идёт не так. Для бизнеса это означает меньше аварий и быстрее путь функции от идеи до пользователя, для команды — меньше ночных выкладок и стресса.

Вот какие эффекты дают фича-флаги на практике:

  • Ниже риск релиза. Новая функция сначала работает у небольшой доли пользователей. Если в ней ошибка, пострадает 1–5% аудитории, а не все клиенты разом.
  • Мгновенный откат (kill switch). Проблемную функцию выключают одним действием, не дожидаясь сборки и деплоя предыдущей версии. Время простоя измеряется минутами, а не часами.
  • Чаще и мельче релизы. Недоделанный код можно безопасно отправлять в основную ветку и на продакшен — выключенным. Команда поставляет изменения непрерывно, а time-to-market сокращается.
  • Проверка на реальных пользователях. Функцию включают для сотрудников, затем для бета-группы лояльных клиентов и только потом для всех. Ошибки, которые не воспроизводятся на тестовом стенде, находятся до массового запуска.
  • A/B-эксперименты. Флаг с двумя вариантами превращается в эксперимент: половина аудитории видит новый онбординг, половина — старый, а решение принимают по конверсии, а не по мнению.
  • Запуск «к дате». Функцию для акции или пресс-релиза выкатывают заранее и включают ровно в нужный момент — без ночного деплоя в день запуска.
  • Тарифы и доступ по ролям. Флаги прав доступа открывают функции только клиентам на определённом тарифе или только администраторам, не дублируя код.

Кто решает, когда включать: роль продакта и бизнеса

С флагами решение «когда показать функцию пользователям» переходит от разработки к продукту. Разработчики отвечают за то, чтобы код был готов, протестирован и безопасно выключен по умолчанию. А когда открыть его бета-группе, на какой процент расширить и когда включить для всех — решает владелец продукта, опираясь на метрики и планы маркетинга.

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

Какие бывают виды feature flags

Флаги различаются по назначению, сроку жизни и тому, как часто меняется их значение. Пит Ходжсон в разборе на сайте Мартина Фаулера выделяет четыре категории: флаги релиза, флаги экспериментов, операционные флаги и флаги прав доступа. От категории зависит, кто управляет флагом, как его тестировать и когда удалять.

ТипДля чегоСрок жизниКак часто меняетсяКто переключает
Release (флаг релиза)Скрыть недоделанную функцию и постепенно раскатить готовуюКороткий: по Фаулеру — обычно не дольше недели-двухРедко, статичное значениеВладелец продукта, команда разработки
Experiment (эксперимент)A/B и мультивариантные тестыЧасы–недели, до статистически значимого результатаОчень динамично, решение на каждый запросПродакт, аналитик
Ops (операционный, kill switch)Отключить тяжёлую или проблемную функцию, деградировать под нагрузкойОбычно короткий, но аварийные выключатели живут долгоРедко, но переключать нужно очень быстроДежурный инженер, SRE
Permission (права доступа)Открыть функцию тарифу, роли, бета-тестерамГодыРешение на каждый запросПродукт, продажи, поддержка
Remote config (смежный инструмент)Менять параметры без релиза: тексты, лимиты, порядок блоковДолгийПо необходимостиПродукт, маркетинг

Флаг релиза — самый частый тип. Например, команда переделывает корзину интернет-магазина: работа идёт три спринта, и всё это время новый код живёт в основной ветке, но выключен. Когда корзина готова, её включают сотрудникам, затем 5% покупателей, затем всем — а через пару недель флаг и старую корзину удаляют.

Флаг эксперимента делит аудиторию на группы. Скажем, продакт сомневается, какой онбординг лучше — короткий из трёх экранов или подробный из шести. Флаг отправляет половину новых пользователей в один вариант, половину — в другой, а через две недели команда сравнивает удержание и оставляет победителя. Такой подход хорошо продолжает логику проверки гипотез, о которой мы писали в статье о создании MVP.

Операционный флаг страхует сервис в нештатной ситуации. Блок персональных рекомендаций нагружает базу данных; в обычный день это незаметно, а в распродажу может уронить сайт. Операционный флаг позволяет отключить рекомендации на время пика и сохранить главное — оформление заказов. Где именно находится предел нагрузки, заранее показывает нагрузочное тестирование.

Флаг прав доступа открывает функцию только определённым пользователям: например, расширенную аналитику — клиентам на тарифе PRO, а новый раздел — участникам бета-программы. Такие флаги живут годами и по сути становятся частью бизнес-логики, поэтому их проектируют аккуратнее, чем временные.

Как работают флаги: где хранить и как принимать решение

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

Где живёт флаг

Есть три основных варианта хранения, и проекты обычно проходят их по очереди по мере роста:

Где хранитсяПлюсыМинусы
В коде, конфиге или переменных окруженияПросто, бесплатно, не нужны новые сервисыПереключение требует перезапуска или деплоя; нет процентов, сегментов и журнала изменений
В своей базе данных с админкойПереключение без деплоя, полный контроль над даннымиПроценты, таргетинг, аудит и SDK для всех платформ придётся писать и поддерживать самим
Во внешнем сервисе флаговГотовые проценты, сегменты, права, аудит, SDK для веба и мобайла, экспериментыЕщё один компонент инфраструктуры или подписка; зависимость от поставщика

Для пары аварийных выключателей хватит первого варианта. Но как только флагов становится больше пяти-десяти и появляется поэтапная раскатка, самописное решение начинает отнимать время у продуктовой разработки — и выгоднее взять готовую платформу.

Серверные и клиентские флаги

Серверный флаг вычисляется на бэкенде: пользователь получает уже готовый результат и не знает, что за ним стоит условие. Клиентский флаг вычисляется в браузере или мобильном приложении — SDK загружает значения флагов и решает, какой интерфейс показать.

Для мобильных приложений клиентские флаги и remote config особенно важны. Новую версию в App Store, Google Play или RuStore нельзя откатить мгновенно: пользователи обновляются неделями, а часть не обновляется вовсе. Если в версии нашлась ошибка, флаг позволяет выключить проблемную функцию на сервере у всех установленных копий — это фактически единственная быстрая страховка в мобильной разработке.

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

Таргетинг: кому включать

Таргетинг — это правила, по которым сервис решает, включён ли флаг для конкретного пользователя. Типичные варианты:

  • процент аудитории — например, 5% случайных пользователей;
  • сегмент — новые клиенты, клиенты с заказами, корпоративные аккаунты;
  • география и язык — один регион или страна;
  • роль и тариф — администраторы, PRO-клиенты;
  • внутренние пользователи — сотрудники компании и тестировщики;
  • платформа и версия приложения — только Android, только версия 5.2 и выше.

Ключевое свойство процентной раскатки — липкость: один и тот же пользователь должен стабильно попадать в одну группу. Иначе он то видит новую корзину, то не видит, а данные эксперимента становятся мусором. Липкость обеспечивают хешированием: от идентификатора пользователя и названия флага считают хеш, переводят в число от 0 до 99 и сравнивают с процентом раскатки. При расширении с 5% до 25% уже включённые пользователи остаются в группе.

Как выкатить функцию под флагом: пошагово

Выпуск функции под флагом — это последовательность ступеней, на каждой из которых аудитория растёт, а команда проверяет метрики и готова откатиться. Процесс ниже мы используем как базовый; конкретные проценты и сроки подбирают под трафик проекта.

Постепенная раскатка функции на растущую долю пользователей
  1. Заведите флаг с описанием. Заполните шаблон: название, тип (релиз, эксперимент, операционный, права доступа), владелец, цель, плановая дата удаления, метрики успеха и критерии отката. Сразу создайте задачу в бэклоге на удаление флага.
  2. Задеплойте код с выключенным флагом. Новая функция уходит на продакшен, но значение по умолчанию — «выключено». Пользователи видят старое поведение, а вы проверяете, что сам деплой ничего не сломал.
  3. Включите для команды и тестировщиков. Сотрудники и QA пользуются функцией на реальном продакшене, с настоящими данными и интеграциями. Здесь всплывают ошибки, которые не воспроизводятся на тестовом стенде.
  4. Откройте 1–5% пользователей. Сравнивайте включённую группу с контрольной: долю ошибок, время ответа, падения приложения и ключевую бизнес-метрику — например, долю оформленных заказов.
  5. Расширьте до 25%, затем до 50%. Критерии остановки фиксируются заранее: если доля ошибок выросла сильнее порога или конверсия просела, флаг выключают без долгих обсуждений, а причину разбирают уже после.
  6. Включите для 100%. Когда метрики стабильны на половине аудитории, откройте функцию всем и выдержите контрольный период наблюдения.
  7. Удалите флаг и старый код. Уберите проверку флага, старую ветку поведения, тесты для неё и запись в сервисе флагов. Только после этого релиз можно считать завершённым.

Ориентировочная схема этапов выглядит так (сроки — пример для сервиса со средним трафиком; при малом трафике каждую ступень держат дольше, чтобы набрать достаточно данных):

ЭтапАудиторияСколько держатьЧто смотретьКритерий отката
ВнутреннийСотрудники, QA1–3 дняОшибки в логах, обратная связь командыЛюбая блокирующая ошибка
Канарейка1–5%1–2 дняДоля ошибок, время ответа, падения клиентаОшибки выше контрольной группы
Расширение25%2–3 дняТе же метрики + бизнес-метрикаПросадка конверсии или рост обращений
Половина50%2–3 дняНагрузка на базу и внешние сервисыРост нагрузки сверх запаса
Полный запуск100%1–2 недели наблюденияВсе метрики относительно периода до запускаУстойчивое ухудшение метрик
Очистка—Ближайший спринтФлаг и старый код удалены—

Feature flags, CI/CD и trunk-based development

Feature flags — естественное дополнение к CI/CD: конвейер отвечает за то, чтобы код быстро и надёжно попадал на продакшен, а флаги — за то, когда пользователи увидят результат. Без флагов непрерывная поставка упирается в простую проблему: что делать с функцией, которая будет готова только через месяц?

Ответ — trunk-based development. Исследовательская программа DORA описывает эту практику так: разработчики сливают небольшие порции изменений в основную ветку как минимум раз в день, держат не больше трёх активных веток и обходятся без периодов заморозки кода и длинных фаз интеграции; команды с такой практикой показывают более высокую скорость и стабильность поставки. По нашему опыту, именно флаги делают такой режим реальным: недоделанная функция живёт в основной ветке выключенной, не мешает релизам и не превращается в долгоживущую ветку с болезненным слиянием. Подробнее о самом конвейере — в статье о CI/CD простыми словами.

Флаги часто путают с инфраструктурными способами безопасного релиза. Разница — в уровне, на котором происходит переключение:

ПодходЧто переключаетГранулярностьСкорость отката
Canary deploymentДолю трафика между старой и новой версией приложенияВся сборка целикомМинуты: трафик возвращают на старую версию
Blue-green deploymentВесь трафик между двумя одинаковыми окружениямиВся сборка целикомМинуты: переключение балансировщика
Feature flagКонкретную функцию внутри одной версииОтдельная функция, пользователь, сегментСекунды: смена значения флага

Подходы не конкурируют, а дополняют друг друга. Canary и blue-green отвечают на вопрос «работает ли новая сборка», флаги — «как пользователи реагируют на новую функцию». Отдельный приём — dark launch, или «тёмный запуск»: новый код выполняется на реальном трафике, но его результат пользователю не показывают. Так проверяют, выдержит ли, например, новый поисковый движок продакшен-нагрузку, до того как переключить на него выдачу.

Инструменты: сделать самим или взять готовую платформу

Инструмент для feature flags выбирают по трём вопросам: сколько флагов и платформ в проекте, нужны ли проценты, сегменты и эксперименты, и где можно хранить данные о пользователях. Универсального ответа нет — есть разумный вариант под масштаб.

ВариантКогда подходитПлюсыМинусы
Флаг в конфиге или переменной окружения2–5 аварийных выключателей, небольшой проектНоль затрат, понятно всемНет процентов и аудита, переключение через перезапуск
Свой сервис флаговОсобые требования к логике или интеграциямПолный контрольДолго делать и дорого поддерживать, SDK под каждую платформу
Open-source self-hosted: Unleash, Flagsmith, GrowthBookНужны проценты, сегменты и аудит, данные хранятся у себяЗрелая функциональность, разворачивается на своей инфраструктуреСервис нужно администрировать и обновлять
Встроенные: GitLab Feature Flags, Firebase Remote ConfigКоманда уже живёт в GitLab; мобильное приложение на FirebaseНе нужен отдельный продуктФункциональность скромнее специализированных платформ
SaaS: LaunchDarkly и аналогиБольшие команды, сложные экспериментыМаксимум возможностей, ничего не администрироватьПодписка, данные у поставщика, зависимость от его доступности

Например, в GitLab флаги встроены прямо в проект и совместимы с клиентскими библиотеками Unleash, а саму платформу Unleash можно развернуть на собственных серверах. Для российских проектов self-hosted-вариант часто предпочтительнее: данные о пользователях и правила таргетинга остаются в своём контуре, а работа релизного процесса не зависит от доступности зарубежного облачного сервиса. Если в атрибутах таргетинга есть персональные данные, этот выбор стоит согласовать с тем, кто отвечает в компании за их обработку.

Чтобы не привязываться к конкретному поставщику, имеет смысл с самого начала использовать OpenFeature — вендор-нейтральный стандарт API для работы с флагами. Проект принят в Cloud Native Computing Foundation в 2022 году и с ноября 2023 года имеет статус Incubating. Код приложения обращается к флагам через единый интерфейс, а конкретная платформа подключается как провайдер — сменить её позже можно без переписывания всех проверок.

Как внедрить feature flags в проект

Внедрение флагов — это не только установка SDK, но и набор договорённостей: как называть флаги, кто ими управляет, что происходит при сбое и когда их удаляют. Начинать стоит с малого, чтобы процесс прижился раньше, чем флагов станет много.

  1. Начните с одного kill switch. Выберите самую рискованную функцию — оплату, интеграцию с внешним сервисом, тяжёлый отчёт — и поставьте на неё аварийный выключатель. На нём команда отработает весь цикл.
  2. Договоритесь о нейминге и шаблоне. Название отражает функцию и тип: release_new_checkout, ops_disable_recommendations. Описание по шаблону — владелец, цель, дата удаления, метрики.
  3. Настройте права и аудит. Определите, кто может переключать флаги на продакшене, а кто только на тестовых окружениях. Журнал изменений обязателен: кто, когда и что переключил — первое, что ищут при разборе инцидента. Доступ к панели флагов на продакшене — это доступ к поведению продукта, его защищают так же, как доступ к деплою.
  4. Задайте безопасное значение по умолчанию. Если сервис флагов недоступен, SDK должен вернуть заранее определённое значение — как правило, «старое поведение». Приложение не должно падать или зависать из-за недоступности флагов.
  5. Заведите реестр активных флагов. Дашборд или страница со списком флагов, их владельцами, возрастом и состоянием. Без него флаги теряются, а через год никто не помнит, зачем нужна половина из них.

Проще всего заложить флаги ещё на этапе разработки веб-приложений: тогда архитектура изначально учитывает переключаемые функции, а SDK, права и реестр появляются вместе с первым релизом, а не в разгар инцидента.

Флаги и миграции базы данных

Флаг переключает код, но не откатывает схему базы данных. Если новая функция требует новой колонки или таблицы, изменения проводят в три шага по схеме expand/contract:

  1. Expand. Добавляют новую структуру так, чтобы старый код продолжал работать: новая колонка допускает пустые значения, старая не удаляется.
  2. Переключение флагом. Новый код пишет и читает новую структуру, старый — старую; флаг постепенно переводит пользователей на новую версию, при необходимости данные синхронизируются.
  3. Contract. Когда флаг включён для всех и удалён, старую структуру убирают отдельной миграцией.

Тот же принцип помогает при замене целых модулей: флаг направляет часть запросов в новый сервис, а остальные — в старый, пока новый не докажет надёжность. Подробнее о таком постепенном подходе — в статье о миграции legacy-системы без поломок.

Флаги в микросервисах

Когда функция затрагивает несколько сервисов, флаг должен быть согласован между ними. Основные правила:

  • у флага один источник правды — общий сервис флагов, а не копии в конфигах каждого сервиса;
  • решение по флагу принимают один раз на входе запроса и передают дальше в контексте, чтобы разные сервисы не получили разные ответы для одного пользователя;
  • сервисы, которые читают флаг, совместимы с обоими его состояниями — порядок их деплоя не должен иметь значения;
  • при удалении флага сначала убирают его использование во всех сервисах, и только потом — сам флаг.

Как тестировать код с флагами

Тестирование кода с флагами — это проверка всех состояний, в которых система реально может оказаться у пользователей, а не всех теоретически возможных комбинаций. Каждый флаг удваивает число вариантов поведения: при 10 независимых флагах получается 210, то есть 1024 состояния, и проверить их все невозможно.

Практичная стратегия выглядит так:

  • Обе ветки каждого активного флага. Для новой функции есть тесты и при включённом, и при выключенном флаге — ведь до полного запуска обе ветки работают у реальных пользователей.
  • Конфигурация «как на продакшене». Автотесты прогоняются с текущими значениями флагов на проде: это то, что пользователи видят прямо сейчас.
  • Конфигурация «всё новое включено». Вариант, к которому система придёт после раскатки: он ловит конфликты между функциями, которые разрабатывали параллельно.
  • Флаги в e2e-тестах. Тесты явно задают значения флагов, а не зависят от состояния общего сервиса — иначе они начнут падать, когда кто-то переключит флаг на стенде.

Отдельный полезный приём из разбора Фаулера — «бомба замедленного действия»: тест, который падает, если флаг дожил до плановой даты удаления. Он превращает забытый флаг из тихого долга в красную сборку, которую нельзя не заметить. Как встроить такие проверки в общую стратегию автотестов, мы разбирали в статье об автоматизации тестирования.

Какие метрики смотреть при раскатке

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

МетрикаЧто сигналитПорог для паузы (пример)
Доля ошибок (5xx, исключения)Функция ломается в реальных условияхЗаметно выше, чем в контрольной группе
Время ответа (p95)Новый код медленнее или нагружает базуРост p95 сверх заранее согласованного запаса
Падения клиента, crash-freeОшибка в мобильном приложении или во фронтендеСнижение доли сессий без падений во включённой группе
Бизнес-метрика (конверсия, оформление заказа)Функция работает, но мешает пользователямСтатистически значимая просадка относительно контроля
Обращения в поддержкуПользователи не понимают новую функциюВсплеск обращений по теме функции

Чтобы метрики можно было разделить по группам, значение флага передают в логи, трейсы и аналитику как атрибут события. Тогда на дашборде видно не просто «ошибок стало больше», а «ошибок стало больше именно у тех, кому включили новую корзину».

Следующий уровень зрелости — автоматический kill switch: алерт мониторинга при превышении порога сам выключает флаг и уведомляет владельца. Это сокращает время реакции с минут до секунд, но требует хорошо настроенных порогов, иначе флаг будет выключаться от случайных колебаний. О том, как выстроить мониторинг и реагирование после релиза, — в статье об SRE-поддержке.

Технический долг флагов: как не превратить код в лабиринт

Технический долг флагов — это устаревшие флаги и мёртвые ветки кода, которые остаются в проекте после того, как функция давно запущена или отменена. В разборе на сайте Фаулера есть точная формулировка: опытные команды относятся к флагам как к складским запасам, у которых есть стоимость хранения, и стараются держать их как можно меньше. Каждый забытый флаг усложняет чтение кода, удваивает число сценариев для тестов и хранит в себе выключенную, но живую логику.

Именно такая «спящая» логика сыграла роль в истории Knight Capital. Согласно материалам SEC, 1 августа 2012 года при деплое нового кода для программы Retail Liquidity Program Нью-Йоркской фондовой биржи была активирована давно не использовавшаяся дефектная функция. Её код годами лежал в системе, хотя не применялся.

Распространённая трактовка инцидента такова: новый код повторно использовал флаг, который раньше управлял старой функцией, а на одном из серверов новую версию не установили. Когда флаг включили, этот сервер «разбудил» мёртвый код, и за 45 минут после открытия рынка убыток превысил 460 млн долларов. Позже SEC оштрафовала компанию на 12 млн долларов.

Урок из этой истории для любой команды: не переиспользовать старые флаги, удалять мёртвый код вместе с флагом и следить, чтобы версия на всех серверах была одинаковой. Практические правила, которые мы применяем в проектах:

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

Когда feature flags не нужны

Feature flags не нужны там, где они добавляют сложность, но не снижают риск. Флаг — это дополнительный код, тесты и процесс, и в ряде ситуаций эти затраты не окупаются:

  • Мелкие безопасные правки. Исправление опечатки, смена цвета кнопки или текста подсказки не требуют поэтапной раскатки — их проще выкатить обычным релизом.
  • Необратимые изменения данных. Если функция удаляет или преобразует данные, выключение флага не вернёт их обратно. Здесь нужны резервные копии, сухие прогоны и план миграции, а не флаг.
  • Изменения, обязательные для всех сразу. Требования закона, исправления уязвимостей и обновления пользовательского соглашения должны заработать у всех одновременно — постепенная раскатка здесь неуместна.
  • Нет процесса удаления. Если в команде некому следить за флагами, они превратятся в долг быстрее, чем принесут пользу. Сначала договорённости, потом флаги.

Мартин Фаулер и Пит Ходжсон отдельно подчёркивают, что флаг релиза — не первый, а последний выбор. Если функцию можно разбить на мелкие части, каждая из которых безопасна и полезна сама по себе, лучше выпускать их обычными релизами. Флаг нужен, когда разбить не получается и незаконченный результат нельзя показывать пользователям.

Чек-лист: флаг перед созданием и после раскатки

Этот чек-лист помогает завести флаг правильно и не забыть закрыть его после релиза. Его удобно добавить в шаблон задачи или pull request.

  • ☐ Определены тип флага (релиз, эксперимент, операционный, права доступа) и цель.
  • ☐ Назначен владелец — конкретный человек.
  • ☐ Указана плановая дата удаления.
  • ☐ Задано безопасное значение по умолчанию на случай сбоя сервиса флагов.
  • ☐ Определены метрики успеха и критерии отката.
  • ☐ Понятно, кто вправе переключать флаг на продакшене.
  • ☐ Обе ветки поведения покрыты тестами.
  • ☐ Флаг внесён в реестр активных флагов.
  • ☐ В бэклоге создана задача на удаление флага.
  • ☐ После раскатки удалены проверка флага, старая ветка кода и её тесты.

Частые вопросы о feature flags

Чем feature flag отличается от канареечного релиза?

Канареечный релиз переключает трафик между версиями приложения на уровне инфраструктуры, а feature flag включает конкретную функцию внутри одной версии кода. Canary отвечает на вопрос «работает ли новая сборка», флаг — «как пользователи реагируют на новую функцию». На практике подходы сочетают: сборку раскатывают канарейкой, а рискованные функции в ней держат под флагами.

Замедляют ли флаги работу приложения?

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

Можно ли использовать feature flags в мобильном приложении?

Да, и там они особенно полезны. Новую версию в App Store, Google Play или RuStore нельзя мгновенно откатить, а пользователи обновляются неделями. Флаги и remote config позволяют выключить сломанную функцию на сервере у всех установленных версий. Важно помнить, что клиентская логика видна пользователю, поэтому секреты и проверки прав за флагом не прячут.

Сколько флагов в проекте — это нормально?

Универсальной цифры нет: важно не количество, а то, что у каждого временного флага есть владелец и дата удаления. Долгоживущие флаги прав доступа и аварийные выключатели могут жить годами. Тревожный сигнал — когда команда не может быстро ответить, зачем нужен флаг и можно ли его удалить.

Нужен ли платный сервис, или хватит своего решения?

Для нескольких аварийных выключателей хватит флагов в конфигурации или базе данных. Когда нужны проценты раскатки, сегменты, аудит изменений и права доступа, дешевле взять готовую платформу: open-source и self-hosted (Unleash, Flagsmith, GrowthBook), встроенные флаги GitLab или облачный SaaS. Стандарт OpenFeature позволяет позже сменить поставщика без переписывания кода.

Когда удалять флаг после релиза?

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

Хотите выпускать релизы без ночных откатов?

Настроим feature flags, CI/CD и постепенную раскатку, чтобы новые функции включались по кнопке и выключались за секунды — без нового деплоя.

Настроить DevOps-процессы