フィーチャーフラグとフィーチャーリリース
Feature Flag (FF)は、コードを解放せずにシステムの動作を有効/無効にする管理条件です。フラグを使用すると、次のことができます。機能を安全にロールアウトし、ユーザー/マーケット/テナントのターゲットグループを作成し、問題のあるコンポーネントをすばやく無効にし、実験を行い、実行時にパラメータを設定します。
主な目的:- リリースのブラスト半径を削減します。
- 別々の展開とアクティベーション。
- 監査、SLO、ワンクリックロールバックにより、透過的な変更管理を可能にします。
1)フラグの種類と適用時期
リリースフラグ-新しい機能(ダーク→カナリア→ランプアップ→100%)を段階的に含める。
Ops/kill-switch-依存関係の即時切断(プロバイダ、サブシステム、重い計算)。
実験(A/B、マルチバリアント)-バリアントへのトラフィックの分割(重み、粘着バケット)。
権限/権限-役割/計画/管轄による機能へのアクセス。
Remote Config-flag/configからの動作パラメータ(閾値、タイムアウト、数式)。
マイグレーションフラグ-スキーム/データパスの切り替え(新しいインデックス/DB/エンドポイントに移動)。
アンチパターン:同じフラグ「about everything」-フィーチャー、コンプスイッチ、パラメータに分割されます。
2)フラグデータモデル(最小)
yaml flag:
key: "catalog. new_ranker"
type: "release" # release ops kill experiment permission config migration description: "New Directory Ranking"
owner: "search-team@company"
created_at: "2025-10-01T10:00:00Z"
ttl: "2026-01-31" # delete deadline after 100% enable rules:
- when:
tenant_id: ["brand_eu","brand_latam"]
region: ["EE","BR"]
user_pct: 10 # progressive percentage then: "on"
- when:
kyc_tier: ["unverified"]
then: "off"
variants: # for experiments
- name: "control"; weight: 50
- name: "v1"; weight: 30
- name: "v2"; weight: 20 payload:
v1:
boost_freshness: 0. 3 boost_jackpot: 0. 2 v2:
boost_freshness: 0. 2 boost_jackpot: 0. 4 prerequisites: # dependent flags/schema versions
- key: "catalog. index_v2_ready"
must_be: "on"
audit:
require_ticket: true change_window: "09:00-19:00 Europe/Kyiv"
safeguards:
max_rollout_pct: 50 # stop threshold auto_rollback_on:
p95_ms: ">200"
error_rate: ">2%"
3)評価・ターゲティング
Ключи tenant_id、地域/ライセンス、通貨、チャネル、ロケール、ロール、計画、デバイス、user_id、コホート、kyc_tier、 experiment_bucket'。
評価順序:前提条件→ルールを拒否→ルールを許可→デフォルト。
Sticky Bucketing:実験では、安定した識別子('hash (user_id、 flag_key)'など)をハッシュして、ユーザーが常に1つのオプションを取得するようにします。
ts result = evaluate(flag, context) // pure function if (!prereqs_ok(result)) return OFF if (deny_match(result, ctx)) return OFF if (allow_match(result, ctx)) return resolve_variant_or_on(result, ctx)
return flag. default
4) FF分布とアーキテクチャ
オプション:- サーバーサイドSDK(推奨):バックエンドの真実とキャッシュのソース;論理の統一。
- エッジ/CDN評価:周囲(PII/シークレットがない場所)での高速ターゲティング。
- クライアント側のSDK: UIパーソナライゼーションが必要な場合でも、コンテキストを最小限に抑え、機密性の高いルールを持たない場合。
- Config-as-Code:リポジトリ内のフラグの保存、CI検証、CD経由のロールアウト。
- 起動ブートストラップ+ストリーミングアップデート(SSE/gRPC)+最後のスナップショットへのフォールバック。
- SLA 「freshness」フラグ:p95 ≤ 5 s。
5)リリース戦略
5.1ダーク・ローンチ
この機能は有効ですが、ユーザーには見えません。メトリクスとエラーを収集します。
5.2カナリア島
私達は1つの管轄/テナントの交通の1-5%を含んでいます;モニターp95/p99、エラー、変換。
停止条件-メトリックによるオートカトフしきい値トリガ。
5.3プログレッシブロールアウト
10%→25%→50%→100%手動/自動検証でスケジュール。
5.4シャドウ/ミラーリング
新しいパスにリクエストを複製し(明らかな効果はありません)、結果/レイテンシーを比較します。
5.5ブルー/グリーン+FF
2つのバージョンを展開します。フラグはトラフィックを制御し、依存関係をセグメントごとに切り替えます。
6)依存関係とクロスサービスの一貫性
準備の前提条件と「健康フラグ」を使用する:インデックスが構築され、移行が完了します。
イベントを通じた調整:'FlagChanged (flag_key、スコープ、new_state)'。
1.enable read-path→2) check metrics→3) write/side-effectsを有効にします。
- サービス契約:デフォルトはフェイルセーフOFFでなければなりません。
7)観察可能性およびSLO
フラグ/バリアント/セグメントごとのメトリック:- 'flag_eval_p95_ms'、' errors_rate'、'config_freshness_ms'
- ビジネスメトリック:'ctr'、 'conversion'、 'ARPU'、 'retention'、ガードレール(例:RGインシデント)。
- オートカトパの自動SLOしきい値。
ログ/トレース:'flag_key'、 'variant'、 'decision_source' (server/edge/client)、 'context_hash'を追加します。
ダッシュボード:しきい値を持つ「はしご」をロールアウトします。
8)安全性とコンプライアンス
コンテキストでのPII最小化。
RLS/ACL:どのフラグを変更できるか(ドメイン/マーケット別)。
変更の時間ウィンドウ(変更ウィンドウ)と敏感なフラグのための「二重確認」。
不変監査:who/when/what/why(チケット/インシデントリンク)。
管轄区域:フラグは規制禁止を回避してはなりません(例えば、禁止された国でのプレーを含む)。
9)長寿命フラグの管理
各フラグにはTTL/削除日があります。
100%インクルード後-コードブランチを削除するタスクを作成します。そうでなければ「、フラグデット」が増加します。
フラグを'migration'/'one-time'としてマークし、定数'permission/config'から分離します。
10)サンプル契約API/SDK
評価API(サーバーサイド)
http
POST /v1/flags/evaluate
Headers: X-Tenant: brand_eu
Body: { "keys":["catalog. new_ranker","rgs. killswitch"], "context": { "user_id":"u42", "region":"EE" } }
→ 200
{
"catalog. new_ranker": { "on": true, "variant":"v1", "as_of":"2025-10-31T12:10:02Z" },
"rgs. killswitch": { "on": false, "variant":null, "as_of":"2025-10-31T12:10:02Z" }
}
クライアントSDK (кэш、フォールバック)
ts const ff = await sdk. getSnapshot() // bootstrap const on = ff. isOn("catalog. new_ranker", ctx)
const payload = ff. payload("catalog. new_ranker", "v1")
11)他の回路との相互作用
レート制限/クォータ:フラグは、インシデントの期間中、RPSを下げたり、スロットリングを有効にしたりできます。
回路ブレーカ/劣化:kill-switchiは重いパスを無効にし、劣化を可能にします。
ディレクトリ/パーソナライゼーション:フラグは(Remote Configを使用して)重み/ランキングルールを変更します。
データベース移行:フラグは読み取り/書き込みを新しいスキーム(read-replica→dual-write→write-primary)に徐々に変換します。
12) Playbook(ランブック)
1.25%インクルージョン後のインシデント
オートキャットオフは、すべての/セグメント、オンコールへのチケット、統計コレクション、RCAのための→OFFフラグをトリガーしました。
マイグレーションフラグを使用して、分解/古いブランチを一時的に有効にします。
2.p95カタログの成長
しきい値'p95_ms> 200'-autocatoph;'flag_key=catalogでログのスナップショットを修正しました。 。 。
ペイロード設定を有効にします。
3.管轄権の欠如
パーミッションフラグは「NL」-OFF+事後監査で誤ってゲームを開き、ガードルール「region deny」を追加しました。
4.A/Bの分散
実験を停止し、CUPED/層別解析を実行し、更新されたスケールで再ロールします。
13)テスト
単位:規則/優先順位/前提条件の決定論的評価。
契約:フラグスキーム(JSON/YAML)、バリデータ、マージ前のCIチェック。
プロパティベース:「deny> allow」、「最も特定の勝利」、安定したバッケット。
リプレイ-新しい構成で実際のコンテキストを再生します。
E2E:カナリアスクリプト(ステップアップ/ステップダウン)、オートカットオフチェック、および監査イベント。
カオス:崖のストリーミング、レガシースナップショット、大規模なフラグの更新。
14)典型的なエラー
クライアントフラグのシークレットロジック(リーク/スプーフィング)。
TTLの不在→コード内のフラグの「墓地」。
→セグメンテーションのない「ユニバーサル」フラグは問題をローカライズできません。
ガードレール/オートカトフォンなし-手動インシデント。
flags→loops/out of sync間の互換性のない依存関係。
キャッシュ→レイテンシスパイクのない各リクエストのフラグの評価。
監査/変更ウィンドウなし-コンプライアンスリスク。
15)売り上げ前のチェックリスト
- タイプ、所有者、説明、TTLおよびチケット要件で作成されたフラグ。
- 定義されたターゲティングルール;不要なリージョン/ロールの'deny'
- 粘着性のあるバッケティングは決定論的です。IDは安定しています。
- 前提条件および健康旗の準備ができた;デフォルトセーフ。
- p95/p99、 error_rate、ビジネスガードレールのダッシュボードとアラート。
- Autocatoffが設定されました。ロールアウト停止しきい値とロールバック条件。
- カナリアプラン-パーセンテージ/マイルストーン/変更ウィンドウ/所有者
- 構成はCIで検証されます。クラスタ/リージョン間で分散されたスナップショット。
- サポート/製品ドキュメント;インシデント・プレイブック。
- 100%後にコードブランチとフラグ自体を削除する計画。
16) 「migration」フラグの例(DB/index)
yaml flag:
key: "search. use_index_v2"
type: "migration"
description: "Switching reads to index v2"
prerequisites:
- key: "search. index_v2_built"
must_be: "on"
rules:
- when: { tenant_id: ["brand_eu"], user_pct: 5 } then: "on"
- when: { tenant_id: ["brand_eu"], user_pct: 25 } then: "on"
safeguards:
auto_rollback_on:
search_p95_ms: ">180"
error_rate: ">1%"
ttl: "2026-02-01"
結論
特徴フラグは「オン/オフ」だけでなく、変化リスク管理の規律です。明確なフラグの種類、決定的なターゲティング、ガードレール付きのプログレッシブディスプレイ、autocathof、監査および削除計画は、リリースを予測可能にし、インシデントを簡潔かつ制御します。市民のファーストクラスとして建築にフラグを構築し、より頻繁に価値を提供し、より安全で、より意味のあるものにすることができます。