Фича-флаги без деплоя

Engineering

Некоторые значения живут в коде, хотя им там не место.

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

«Конфигурация» — это key-value хранилище, и так задумано

Модуль «Конфигурация» в Kookee хранит под ключом любое значение, которое сериализуется в JSON, и отдаёт его через тот же SDK, что и остальной ваш контент:

TypeScript
const flag = await kookee.config.getByKey('feature-new-checkout');

if (flag.value === true) {
  // новое оформление заказа
}

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

TypeScript
const banner = await kookee.config.getByKey('homepage-banner');
// { text: 'Летняя распродажа!', enabled: true, color: '#ff6b00' }

Или бизнес-правило, которым хочет управлять ваш финансовый отдел:

TypeScript
const discount = await kookee.config.getByKey('pricing-discount');
// { percentage: 20, minOrderValue: 50 }

Всё нужное — одним запросом

Запрашивать ключи по одному при каждой загрузке страницы — очевидная ошибка. list() принимает фильтр по ключам:

TypeScript
const configs = await kookee.config.list({
  keys: ['homepage-banner', 'feature-new-checkout', 'pricing-discount'],
});

Один запрос — три значения. Получайте их один раз за рендер на сервере или один раз при запуске приложения на клиенте и передавайте дальше. Каждое чтение конфигурации — это запрос к API в счёт месячного лимита. На бесплатном тарифе это 100 000 запросов в месяц, так что кеширование здесь не преждевременная оптимизация, а обычный способ работы.

История версий страхует от ошибок

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

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

По той же причине описания важнее, чем кажется. enable-v2 ничего не скажет человеку, которому этот ключ достанется через полгода. Пишите описание сразу, когда создаёте ключ.

Чего «Конфигурация» не делает

«Конфигурация» намеренно простая: ключ, значение и история. Она не раскатывает функции на процент аудитории, не включает их отдельным пользователям и не распределяет пользователей по A/B-тестам. Если нужно показать функцию 5% пользователей в Германии, вам нужна отдельная платформа для экспериментов — ей и пользуйтесь.

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

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

TypeScript
let showNewCheckout = false;

try {
  const flag = await kookee.config.getByKey('feature-new-checkout');
  showNewCheckout = flag.value === true;
} catch {
  // сбой сети — оставляем безопасное значение по умолчанию
}

Теперь флагом можно управлять удалённо. Если API недоступен, приложение вернётся к последнему проверенному поведению и не упадёт с исключением на странице оформления заказа.