フィーチャーフラグ運用
フィーチャーフラグの分類、ライフサイクル管理、削除戦略の実践ガイド
フィーチャーフラグ運用とは
フィーチャーフラグ (Feature Flag) の運用は、フラグの作成から削除までのライフサイクルを管理するプラクティスだ。フラグを作るのは簡単だが、不要になったフラグを削除せずに放置すると、コードベースが条件分岐だらけになり技術的負債が蓄積する。
Martin Fowler は自身の bliki 項目「Feature Flag」(2010 年 10 月・以降追記) で、リリースフラグは有用な技術だが本番へ機能を出す手段としては最後の選択肢にすべきで、まず機能を分割して安全に一部ずつ出すことを第一に考えるべきだと書いている。どうしても作りかけの機能を隠す必要があるなら、UI の入口だけを最後に足すキーストーンインターフェースが次の選択肢になる。フラグを足すほど組み合わせ状態は増え、10 個で理論上 1,024 通り (2 の 10 乗) になる。ただしこれがそのままテストすべき件数になるわけではない (後述)。
フラグの 4 分類とライフサイクル
Pete Hodgson が 2017 年 10 月に martinfowler.com へ寄せた記事の分類に基づく 4 種類のフラグは、寿命の長さと、判定をどれだけ動的に切り替える必要があるかの 2 軸で性格が分かれ、管理方針も変わる。
| 分類 | 目的 | 寿命 | 削除目標 | 例 |
|---|---|---|---|---|
| リリースフラグ | 未完成機能を隠す | 短命 | 1〜2 週間 (プロダクト都合でより長く残る場合あり) | 新しい決済フローの段階的公開 |
| 実験フラグ | A/B テスト | 短命 | 数時間〜数週間 (有意な結果が出るまで) | ボタン色の変更による CVR 比較 |
| 運用フラグ | キルスイッチ | 短命〜長命 | 運用面の確信が持てたら削除 (キルスイッチだけ長期残置) | 外部 API 障害時の縮退モード |
| パーミッションフラグ | ユーザー別機能制御 | 長命 | 年単位で残る (機能提供が続く限り維持) | プレミアムユーザー限定機能 |
短命フラグと長命フラグを同じ仕組みで管理すると、短命フラグの削除が後回しになりやすい。分類ごとに管理ルールを分けることが重要だ。
フラグの技術的負債化を防ぐ
削除戦略
フラグ作成時に「削除予定日」をコードコメントとチケットの両方に記録する。
// TODO: 2026-04-15 までに削除 (TICKET-1234)
// リリースフラグ: 新しい検索アルゴリズム
if (featureFlags.isEnabled('new-search-algorithm')) {
return newSearch(query);
}
return legacySearch(query);
CI での期限切れ検出
CI パイプラインで期限切れフラグを検出し、ビルドを警告 (または失敗) させる仕組みを設ける。
# 期限切れの TODO コメントを検出
grep -rn "TODO:.*202[0-9]-[0-9][0-9]-[0-9][0-9]" src/ | while read line; do
date_str=$(echo "$line" | grep -oP '\d{4}-\d{2}-\d{2}')
if [[ "$date_str" < "$(date +%Y-%m-%d)" ]]; then
echo "⚠️ 期限切れフラグ: $line"
fi
done
フラグ数の上限
チーム内でアクティブなフラグ数の上限を設ける (例: 同時に 15 個まで)。上限に達したら、新しいフラグを作る前に既存フラグを削除する。
フラグの実装パターン
シンプルな環境変数方式
// 小規模プロジェクト向け
const isNewUIEnabled = process.env.FEATURE_NEW_UI === 'true';
メリット: 追加の依存なし、デプロイ時に切り替え可能。デメリット: ユーザー単位の制御不可、変更にデプロイが必要。
DynamoDB + Lambda 方式
// サーバーレス環境向け (AWS SDK for JavaScript v3。旧 v2 系はサポート終了済み・2026 年 8 月時点)
import { DynamoDBClient, GetItemCommand } from '@aws-sdk/client-dynamodb';
const ddb = new DynamoDBClient({});
const flags = await ddb.send(new GetItemCommand({
TableName: 'feature-flags',
Key: { flagName: { S: 'new-search' } },
}));
const isEnabled = flags.Item?.enabled?.BOOL ?? false;
メリット: リアルタイム切り替え、ユーザー属性による出し分け可能。デメリット: DynamoDB への依存、レイテンシ増加 (キャッシュで緩和)。
よくある落とし穴
- フラグの放置: 「後で消す」が永遠に来ない。3 ヶ月以上残っているリリースフラグは技術的負債と認定し、優先的に削除する
- 組み合わせテストの誤解: フラグが N 個でも 2 の N 乗通りを全部テストする必要はない。Fowler は、リリースフラグなら「次のリリースで有効になる想定の組み合わせ」と「全フラグ有効」の 2 通りを回せば通常は足りると書いている。むしろ危ないのはフラグ間の依存で、依存関係を最小化し独立してテストできる設計にする
- フラグの入れ子:
if (flagA && flagB && !flagC)のような複合条件は、どの状態で何が起きるか追跡不能になる。フラグは単独で判定し、入れ子にしない - 本番でのフラグ切り替え事故: 運用フラグを誤って無効化し、障害を引き起こす。運用フラグには変更時の承認フローを設ける
フラグ管理の成熟度モデル
フラグ管理の成熟度モデルを以下にまとめる。
| レベル | 状態 | 次のステップ |
|---|---|---|
| 1 | 環境変数でハードコード | フラグ管理の仕組みを導入 |
| 2 | 設定ファイルで管理 | 削除予定日の記録を開始 |
| 3 | CI で期限切れ検出 | フラグ数の上限を設定 |
| 4 | ダッシュボードで可視化 | ユーザーセグメント別の制御 |
| 5 | 自動クリーンアップ | フラグの影響分析と自動テスト |
「Continuous Delivery」(Jez Humble, David Farley 著) でフィーチャーフラグの運用パターンが解説されている。分類とパターンを体系的に整理した Pete Hodgson の記事「Feature Toggles」(martinfowler.com・2017 年) と、Martin Fowler 自身の bliki 項目「Feature Flag」(2010 年) も必読だ。
全体像を把握するには関連書籍も有用。
この記事は役に立ちましたか?