フィーチャーフラグとは 基礎から実装まで
要約
フィーチャーフラグは、コードを再デプロイせずにランタイムで機能をオン・オフ切り替える条件分岐です。トランク・ベース開発や段階的なロールアウトを可能にしますが、時間とともに技術的負債になります。リリース・実験・Ops・パーミッションの4タイプと、200個以上のフラグを保つチームのクリーンアップ戦略を解説します。
フィーチャーフラグは、デプロイを伴わずにランタイムで機能のオン・オフを判定する条件分岐です。これが基本的な考え方です。実践でのフィーチャーフラグとは何か?設定ファイル、データベース行、またはフラグサービスから答えが得られるif文です。コンセプトは単純です。しかし、リポジトリに200個も存在すると、話は複雑になり、このガイドはまさにそこに焦点を当てています。
フィーチャーフラグはコードでどのように見えるか
最小限でも実用的なバージョンは次の通りです。
if (flags.isEnabled("new-checkout", { userId })) {
return renderNewCheckout();
}
return renderOldCheckout();両方のコードパスは同じビルドに含まれます。フラグ値は再デプロイなしで変更できる場所にあります。環境変数、JSONファイル、テーブル、またはホストされたサービスです。値を変更すると、次の評価時に動作が変わります。
この分離がポイントです。デプロイメントはサーバーにコードを配置することです。リリースはユーザーがそれを見ることです。フラグはこの2つのイベントを分割するため、mainにマージしても「全員が今これを取得する」という意味ではなくなります。

なぜチームはフィーチャーフラグを使用するのか
実際のチーム(エンジニア5~50人)では、同じ3つの理由が何度も浮かび上がります。
未完成の作業を安全にマージする。 完成していない機能をオフのフラグの後ろにコミットし、ブランチが3週間も存在することはありません。これがトランク・ベース開発を実現可能にするものです。
段階的にロールアウトする。 社内ユーザーの場合はオン、トラフィックの5%の場合はオン、その後全員にオンにします。エラー率が上昇した場合、数秒で戻すことができます。
素早く何かを停止させる。 支払いプロバイダーが午前2時に不調になった場合、フラグにより、オンコールは全体リリースをロールバックする代わりに1つの機能をダウングレードできます。
これらのいずれもベンダーを必要としません。フラグは設定テーブルのブール値になります。パーセンテージロールアウト、監査証跡、またはエンジニア以外が物を切り替える必要があるまで、プラットフォームをスキップしてください。
フィーチャーフラグの4つのタイプ
Pete Hodgsonの広く引用されているMartin Fowlerのサイトのフィーチャートグル記事では、フラグはそれがどのくらい存続し、判定がどのくらい頻繁に変わるかによって分類されています。カテゴリーは今でも最も明確なメンタルモデルです。
リリース: 数日~数週間存続、エンジニアによって切り替えられます。例:未完成のチェックアウトの再設計を非表示にする。
実験: 数週間存続、プロダクトと分析によって切り替えられます。例:2つの価格設定ページのA/Bテスト。
Ops: 数時間~永遠に存続、オンコールによって切り替えられます。例:低速のレコメンデーションサービスのキルスイッチ。
パーミッション: 数ヶ月~数年存続、プロダクトと導入支援によって切り替えられます。例:ベータアクセスまたはプレミアムのみの機能。
有効期限の欄が最も重要です。リリースフラグがそのリリースより長く存続している場合、それはまだ見つかっていないバグです。パーミッションフラグがクリーンアップスプリントで削除される場合、それはまだ起こっていない停止です。
フラグを作成する際に、タイプと名前を付けて、ラベルを付けてください。6ヶ月後、誰も「new-nav-v2」がどのカテゴリーのものか覚えていません。

ユーザーに害を及ぼさずにフラグをロールアウトするにはどうしたらよいか
つまらないシーケンスが最適です。
フラグがオフの状態でコードを出荷します。何も変わらなかったことを確認します。
本番環境の自分のチームに対して有効にします。1日それを使用します。
ユーザーの1%~5%に対して有効にします。ユーザーIDで粘着性のあるもので、セッション中に誰も変種間をフリップしません。
エラー率、レイテンシ、および1つのビジネスメトリックを監視します。ダッシュボードをじっと見つめながらではなく、開始する前に閾値を決めてください。
100%にランプアップし、定義された期間待ってから、フラグを削除します。
ステップ5は、チームがスキップするステップです。そこにコストがかかる理由については後で説明します。
評価に関する実用的な注記:フラグ読み込みを安い失敗セーフなものにします。フラグサービスがダウンしている場合、コードにデフォルトが必要です。フラグあたりのデフォルトを選択してください。キルスイッチは「安全」に失敗するはずですが、新しい機能は「オフ」に失敗するはずです。
フィーチャーフラグが技術的負債になるのはなぜか
すべてのフラグはコードのフォークです。2つのフラグは4つの可能なパスを作ります。10個のフラグは1,024個を作ります。そして、あなたはそれらのほんの一握りをテストしたと思っています。GrowthBookのフラグ負債の技術ガイドは、約75%のトグルコンポーネントが導入後最大49週間までコードベースに残っていたことを示す研究を引用しています。ほとんどのデベロッパーが削除予定だと述べていたにもかかわらずです。
同じFowler記事でHodgsonは適切に述べています。賢明なチームはトグルをキャリングコスト付きの在庫として扱い、その在庫を低く保つために機能します。
古典的なホラーストーリーは2012年のKnight Capitalです。廃止されたフィーチャーのフラグが、古いコードがまだ1つのサーバーに存在している間に新しい動作のために再利用されました。そのミスマッチは約1時間以内に約4億6000万ドルの損失に貢献しました。あなたの古いフラグはそれをしないでしょう。より静かなことをします。誰も存在していることを知らない分岐を壊すリファクタリング、または2つのチェックアウトパスのどちらが本当かを理解するために午後を費やす新しい雇用。

既存のコードベースにおいて、すべてのフラグをどのように見つけるか
これは、ベンダードキュメントがスキップする質問であり、ほとんどのチームが立ち往生する場所です。フラグダッシュボードは、何が構成されているかを教えてくれます。それぞれのフラグがコードのどこで読み込まれているか、または「オフ」のフラグの背後にあるコードパスがまだアクセス可能であるかどうかは教えてくれません。
安い手法で始めます。
# ラッパーを介して読み込まれるすべてのリテラルフラグキー
rg -n 'isEnabled\("' src/ | sort
# 定義されているが参照されていないフラグ
comm -23 <(jq -r 'keys[]' flags.json | sort) \
<(rg -o 'isEnabled\("([^"]+)"' -r '$1' src/ | sort -u)これは急速に分解されます。文字列連結から構築されたフラグキーはgrepに表示されません。ヘルパー機能を通じて渡されたフラグは、呼び出しサイトを隠します。モノレポと複数レポ設定は問題を乗算します。同じキーは3つのサービスによって読み込まれる可能性があります。
ここで、ツールでコードを読むことが役立ちます。リポジトリを理解するコード検索ツールは、「new-checkoutが評価される場所と、結果が何に依存するか」という質問に1回のクエリで答えることができます。午後の代わりにgrepします。CursorとGitHub Copilotは1つのリポ内で合理的に対応します。複数のリポにまたがって、すべてのリポにまたがるインデックスが必要です。これはcodebasechatが構築した場合です。
理にかなったフラグクリーンアッププロセスはどのように見えるか
削除を後からのやることではなく、作業の一部として扱ってください。
フラグを使用して削除チケットを作成します。 フラグの説明にリンクします。チケットが存在しない場合、フラグは出荷されません。
すべての非永続的なフラグに所有者と有効期限を設定します。 変更がない約90日は、レビューの合理的なトリガーです。
2つのプルリクエストで削除します。 最初にフラグチェックを削除し、勝利パスを保持します。次に、デッドブランチとそのテストを削除します。小さなdiffはレビュー可能なdiffです。
時限爆弾テストを追加します。 リリースフラグが有効期限を超えるとのテストが失敗することにより、善意が赤いビルドになります。
合計をキャップしてください。 40のアクティブフラグがあり、上限が40の場合、1つを追加すると1つを削除する必要があります。
静的分析はここでも役立ちます。CodeSceneのようなツールは、どのファイルが最も複雑な条件ロジックを運ぶかを示すことができます。これは通常、古いフラグがクラスターする場所です。SonarQubeは、チェックを削除した後の到達不可能でデッドコードにフラグが付けられます。
フラグの背後にあるコードをどのようにテストするか
テストは、誰も予算を立てない部分です。フラグあたり2つのパスを使用して、テストスイートは両方をカバーする必要があります。少なくとも危険な動作を保護するフラグの場合。
実用的に保ってください。ユニットテストで、フラグ値を注入して、ライブサービスを読むのではなく、すべてのリリースフラグのオンとオフの状態をテストします。デフォルトの本番構成に対して1つのエンドツーエンドスイートを実行してください。これは、今日ユーザーが取得するものです。次に、リリースするために機能フラグをオンにして2回目のパスを実行します。
すべての組み合わせをテストしようとしないでください。10個のフラグでは、あなたはできません。代わりに、フラグを独立させてください。別のフラグもオンの場合にのみ動作が変わるフラグは設計の臭いです。これは、分解する最初のものです。
エンジニアは何を誤解しているか
ジュニアは同じ3つの間違いをします。それぞれはレビューで安く予防できます。
ネストされたフラグ。 別のフラグの内側の1つのフラグは、両方がオンの場合にのみ存在するパスを作成します。代わりに、明確な名前の単一のフラグを要求してください。
フラグ名に論理を入れます。 「show-new-nav-to-premium-users-in-eu」のような鍵は、文字列ではなくフラグサービスにある対象ルールをコード化します。
デフォルトを忘れる。 フラグルックアップが失敗した場合、何が起こりますか?プルリクエストの説明で答えを書いてください。
新規雇用の最初の2週間は、彼らが所有者なしの古いフラグに実行する場合です。タイプ、所有者、各エントリの削除日を持つ短いフラグレジストリは、何時間もの周りを聞くことを節約します。
フィーチャーフラグをスキップすべき時
フラグは無料ではないため、次の場合はスキップしてください。
変更は小さく、リバーシブルで、デプロイはロールバックから1回です。フラグは利益のためにコードパスを追加します。
変更はデータベーススキーマに触れ、フラグが隠すことができない方法で進みます。代わりに展開・契約移行を使用してください。
チームはフラグを削除するプロセスがありません。最初にそれを修正するか、将来の読みやすさのために借金をしています。
そして、変更が危険で、ユーザー向けで、再配置によって元に戻すのが難しい場合は、躊躇なくそれらを使用してください。支払いの流れ、認証の変更、およびそれの背後にあるデータ移行はすべて適格です。
10人のチームで実際に何をするか
設定にブール値と1つのラッパー関数を使用して開始し、すべてのフラグ読み込みが1つの場所を通過するようにします。その単一のチョークポイントにより、フラグリストが検索可能、監査可能、後でホストされたサービスに移行しやすくなります。
各フラグをタイプで、所有者を付けてラベルを付け、1日目の削除チケットを提出します。月に1回、10分でリストを確認してください。2週間100%にあったフラグを削除します。
フィーチャーフラグはローンです。危険なリリースを節約するとき、そしてインタレストが次のリファクタリングで表示される前にそれを返すときに摂取してください。