spinny:~/writing $ vim openfeature-feature-flags-progressive-delivery.md
1~2Развертывание — это когда код поступает в производство. Релиз — это когда кто-то действительно может его использовать. Смешение этих двух моментов — один из самых быстрых способов превратить каждое развертывание в немного напряженный момент.3~4feature flag служит для того, чтобы создать пространство между этими двумя моментами. Вы можете развернуть сегодня, запустить завтра для внутренней команды, затем для пилотного клиента, затем для 10% пользователей. Если что-то пойдет не так, выключите флаг. Вам не обязательно выполнять откат всей версии.5~6## Флаг — это не просто if7~8Технически это часто `if`. В культурном отношении это нечто большее.9~10```typescript11if (await flags.isEnabled('checkout.v2.enabled', context)) {12 return newCheckout(input);13}14~15return oldCheckout(input);16```17~18Этот маленький `if` может означать постепенное развертывание, эксперимент, миграцию, разрешение на предпринимательство или kill switch в эксплуатацию. Проблема в том, что если вы плохо с этим справитесь, это также может стать техническим долгом, который останется в коде на два года.19~20## Откуда здесь OpenFeature21~22OpenFeature — открытая спецификация для оценки feature flag с общим API. Идея проста: код вашего приложения не должен напрямую зависеть от поставщика или внутренней системы, которую вы используете для флагов.23~24Приложение спрашивает:25~26```typescript27const enabled = await client.getBooleanValue('checkout.v2.enabled', false, {28 targetingKey: user.id,29 plan: user.plan,30 country: user.country,31});32```33~34Поставщик решает, откуда берутся правила: SaaS, файл, внутренний сервис, flagd, конфигурация GitOps. Если однажды вы измените серверную часть пометки функций, приложение не придется переписывать повсюду.35~36Такое разделение кажется архитектурной деталью, но оно ощущается по мере роста проекта.37~38## Контекст – это половина дела39~40Флаг включения или выключения для всех полезен, но ограничен. Прогрессивная доставка живет в контексте:41~42- внутренний или внешний пользователь;43- бесплатный или корпоративный план;44- деревня;45- организация;46- версия приложения;47- стабильный процент трафика.48~49Важным ключом является `targetingKey`: он должен быть стабильным. Если он меняется при каждом запросе, пользователь может оказаться один раз в варианте А, один раз в варианте Б. Для эксперимента это ужасно, для кассы — катастрофично.50~51## Разумное внедрение52~53Мне нравится такой поток:54~551. развернуть со снятым флагом;562. зажигание для разработчиков и QA;573. включение пилотного заказчика или арендатора;584. 5% внедрение;595. внедрение на уровне 25%;606. 100% внедрение;617. удаление старого кода и флага.62~63Часто забываемый пункт — последний. Временный флаг должен иметь дату смерти. Если она останется навсегда, каждому будущему рефакторингу придется спрашивать: «А полезна ли еще эта ветка?».64~65## Kill switch: сначала подготовь их66~67kill switch — это флаг, который спасает вас, когда внешняя зависимость начинает мешать вам, задание потребляет слишком много ресурсов или новая логика выдает странные ошибки.68~69Хорошая kill switch должна быть:70~71- легко найти;72- задокументировано в Runbook;73- проверялся время от времени;74- наблюдаемый при активации;75- независимый, насколько это возможно, от той части, которая может сломаться.76~77Самое страшное – обнаружить во время аварии, что флаг существует, но никто не знает, работает ли он еще.78~79## Наблюдаемость или непрогрессивная доставка80~81Включить фичу на 10% без учета метрик — это просто оптимизм с несколькими шагами.82~83Каждое внедрение должно отвечать на простые вопросы:84~85- увеличились ли ошибки?86- изменилась ли задержка?87- завершают ли пользователи поток?88- есть ли еще билеты или повторы?89- влияет ли вариант только на один сегмент?90~91OpenFeature поддерживает перехваты для оценки флагов. Они полезны для регистрации ошибок, добавления показателей или привязки рейтинга к trace.92~93## Именование и право собственности94~95Имена имеют значение. `new_ui` ничего не говорит. `checkout.v2.enabled` говорит гораздо больше.96~97Для каждого флага я бы отметил как минимум:98~99- имя;100- описание;101- владелец;102- безопасный дефолт;103- причина, почему оно существует;104- дата или условия удаления.105~106Флаг, не имеющий владельца, почти всегда является флагом, который никто не снимет.107~108## Где их оценивать109~110Фронтенд, бэкенд или периферия? Зависит от.111~112Если флажок установлен для макета, копирования или адаптации, с интерфейсом все в порядке. Если речь идет о разрешениях, выставлении счетов, лимитах или конфиденциальных данных, это должно быть на серверной стороне. Если речь идет о маршрутизации или экспериментах с высоким трафиком, периферия может иметь смысл.113~114Простое правило: интерфейс может улучшить взаимодействие с пользователем, но он не должен быть единственным барьером безопасности.115~116## Заключение117~118Хорошо сделанные feature flag меняют отношения с производством. Они не устраняют риск, но делают его меньшим и более управляемым. Можно выпускать кусочками, наблюдать, останавливаться, возвращаться, учиться.119~120OpenFeature добавляет чистую основу: общий API, взаимозаменяемые поставщики и более удобный способ развития системы. Но дисциплина остается за вами: безопасные настройки по умолчанию, четкие имена, метрики, владельцы и чистота.121~122Лучший флаг — это тот, который помогает вам спокойно отпустить, а затем исчезает, когда он больше не нужен.123~124## Источники125~126- [OpenFeature: Introduction](https://openfeature.dev/docs/reference/intro/)127- [OpenFeature: Node.js SDK](https://openfeature.dev/docs/reference/sdks/server/javascript/)128- [OpenFeature Specification: Flag Evaluation API](https://openfeature.dev/specification/sections/flag-evaluation)129- [OpenFeature: Hooks](https://openfeature.dev/docs/reference/concepts/hooks/)130- [CNCF: OpenFeature](https://www.cncf.io/projects/openfeature/)131~
NORMAL · openfeature-feature-flags-progressive-delivery.md [readonly]131 lines · :q to close