Feature flag (фича-флаг)

8 июля 2026 · ~12 мин чтения

концепция devops релизы деплой a-b-тесты

Feature flag (фича-флаг)

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

История

Сама идея старше термина лет на тридцать. Ещё в 1970-х программисты на C
использовали условную компиляцию — директивы #ifdef, которые включали или
выключали куски кода при сборке программы. Это был «флаг времени компиляции»:
решение принималось один раз, при сборке, и чтобы его поменять, нужно было
пересобрать всё заново.

Современное понимание — «переключатель времени выполнения» (runtime toggle) —
оформилось в эпоху веб-компаний, которым надо было выкатывать код часто и без
простоев. Ключевые вехи:

Сегодня это стандартная практика: флаги встроены в Firebase (Remote Config от
Google), есть у GitLab, GitHub, Amazon, а рынок специализированных сервисов —
LaunchDarkly, Split, Flagsmith, GrowthBook, Unleash — оценивается в миллиарды
долларов.

Что это такое

Представь, что у тебя в системе есть новая функция — например, новый способ
проверки входящих заявок. Классический путь: написал код → протестировал →
задеплоил → функция работает у всех сразу. Если что-то пошло не так — откат,
то есть новый деплой старой версии, паника, простой.

Feature flag разрывает жёсткую связку «код задеплоен = код работает». Код
новой функции попадает на сервер, но оборачивается в условие:

если флаг "новая_проверка" включён:
    выполнить новую проверку
иначе:
    выполнить старую проверку

Само значение флага («включён/выключен») хранится не в коде, а снаружи: в
конфиге, в базе данных, в специальном сервисе. Поменять его можно за секунды —
галочкой в админке, без пересборки и передеплоя.

Из этого простого приёма вырастает несколько разных инструментов. По
классификации Ходжсона:

Важная пара для различения: feature flag vs ветка в git. Ветка изолирует
код до попадания в основную версию; флаг изолирует поведение уже
задеплоенного кода. Флаги позволяют сливать код в основную ветку рано и часто
(это называется trunk-based development), не боясь, что незаконченное сломает
прод. И вторая пара: feature flag vs конфиг. Обычный конфиг читается при
старте программы и один для всех; флаг может вычисляться на каждый запрос и
давать разным пользователям разный ответ.

Аналогии из жизни

Электрощиток в квартире. В щитке стоят автоматы: можно обесточить одну
кухню, не выключая весь дом. Ops toggle работает так же: сломалась одна
«комната» системы — отключил её, остальное живёт.
Где ломается: автомат в щитке либо включён, либо выключен для всех розеток
сразу. А фича-флаг умеет тоньше: «выключено для всех, кроме 5% пользователей
из Москвы». У электрика такой магии нет.

Новое блюдо в ресторане. Шеф уже отработал рецепт, продукты закуплены,
повара обучены — но в печатное меню блюдо не попало. Официанты предлагают его
только «своим» — постоянным гостям, чтобы собрать отзывы. Это permission
toggle: функция физически готова, но доступна избранным.
Где ломается: официант может забыть, кому предлагать, а кому нет — человек
ошибается. Флаг детерминирован: одно и то же правило применяется миллион раз
одинаково. Зато у официанта есть здравый смысл, а флаг с ошибкой в правиле
будет миллион раз одинаково ошибаться.

Репетиция оркестра за закрытым занавесом. Оркестр играет новую программу в
настоящем зале, с настоящей акустикой — но публику ещё не пустили. В IT это
называется dark launch (тёмный запуск): новый код уже обрабатывает реальные
запросы, но его результаты никому не показываются, только записываются для
сравнения со старым кодом.
Где ломается: репетиция не нагружает гардероб и кассы, а тёмный запуск
нагружает систему по-настоящему — новый код ест процессор и память прямо на
проде. Если он прожорлив, «репетиция» уронит и «спектакль».

Как это работает

Разберём путь одного флага — от галочки в админке до поведения системы.

Шаг 1. Объявление. Разработчик заводит флаг с именем, например
skip_blacklist_check, и значением по умолчанию false. Где заводит — зависит
от масштаба: в маленькой системе это поле в конфиг-файле или переменная
окружения, в большой — запись в специальном сервисе флагов.

Шаг 2. Ветвление в коде. Во всех местах, где поведение должно зависеть от
флага, появляется проверка:

flags = load_flags()          # прочитать состояние флагов
if flags["skip_blacklist_check"]:
    log("проверка ЧС пропущена по флагу")
    result = "skipped"
else:
    result = check_blacklist(phone)

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

Шаг 3. Доставка значения. Тут три схемы по нарастанию сложности:

  1. Статическая: флаг в конфиге, читается при старте. Чтобы поменять — правишь
    конфиг и перезапускаешь процесс. Просто, но медленно.
  2. Динамическая с опросом: приложение раз в N секунд спрашивает у сервиса
    флагов «что поменялось?» (это называется polling — периодический опрос).
    Изменение долетает за секунды без рестарта.
  3. Динамическая с push: сервис флагов сам рассылает изменения подписчикам
    через постоянное соединение. Долетает почти мгновенно.

Шаг 4. Таргетинг (прицеливание). В зрелых системах флаг — не просто
да/нет, а правило: «включено для 10% пользователей», «включено для всех, у
кого email на @company.com», «включено в Германии». Чтобы один и тот же
пользователь стабильно попадал в одну и ту же группу, его идентификатор
прогоняют через хеш-функцию (детерминированное превращение строки в число) и
смотрят, в какой процентный «карман» попало число.

Шаг 5. Раскатка и уборка. Типичный жизненный цикл релизного флага:
включили на сотрудниках → на 1% пользователей → посмотрели на ошибки и
метрики → 10% → 50% → 100% → выждали неделю-две → удалили флаг и старую
ветку кода
. Последний шаг — самый важный и самый часто пропускаемый.
Каждый живой флаг удваивает число состояний системы: 10 флагов — это
2^10 = 1024 возможные комбинации поведения, которые никто никогда не
протестирует целиком.

Забытый флаг — это заряженное ружьё

1 августа 2012 года трейдинговая компания Knight Capital потеряла около 460 миллионов долларов за 45 минут. По материалам расследования SEC, при деплое нового кода на один из восьми серверов обновление не попало, а флаг, который переиспользовали для новой функции, активировал на этом сервере мёртвый код восьмилетней давности — тот начал заваливать биржу ордерами. Компания не пережила этот день как самостоятельный бизнес. Мораль: флаги нужно удалять, а не переиспользовать.

Где встречается в обычной жизни

Где встречается в IT и бизнесе

Кто пользуется

Альтернативы и конкуренты

Когда НЕ стоит использовать

Флаг — это кредит, а не подарок

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

Связанные понятия

Литература и источники

Где встретилось у меня

Вчера чинил бизнес-агента, который передаёт заявки в колл-центр: этап проверки
номеров по чёрному списку сломался из-за изменений на стороне внешнего
SSO-сервиса, и вместо ожидания чужого фикса мы провели через все слои системы
— от веб-интерфейса до консольного конвейера — флаг «Пропустить ЧС». Классический
ops toggle: система продолжает работать в упрощённом режиме, а флаг выключим,
когда внешний сервис починят.

Краткое резюме