フィーチャーフラグ
コードをデプロイした後に、機能の有効/無効を動的に切り替える仕組み
デプロイ運用
フィーチャーフラグとは
フィーチャーフラグ (Feature Flag / Feature Toggle) は、コードをデプロイした後に、設定値の変更だけで機能の有効/無効を切り替える仕組みである。未完成の機能をメインブランチにマージしつつ本番では無効にしたり、特定のユーザーにだけ新機能を公開したりできる。
Martin Fowler が 2010 年に「Feature Toggles」として体系化し、トランクベース開発やカナリアリリースの基盤技術として広く採用されている。
基本的な実装
// シンプルなフィーチャーフラグ
if (featureFlags.isEnabled('new-checkout-flow', { userId })) {
return renderNewCheckout();
} else {
return renderLegacyCheckout();
}
フラグの 4 分類
| 種類 | 寿命 | 動的性 | 用途 |
|---|---|---|---|
| リリースフラグ | 数日〜数週間 | 静的 | 未完成機能を隠す |
| 実験フラグ | 数週間〜数ヶ月 | 動的 | A/B テスト |
| 運用フラグ | 長期 | 動的 | キルスイッチ、サーキットブレーカー |
| パーミッションフラグ | 長期 | 動的 | ユーザーごとの機能制御 |
リリースフラグは短命で、機能が安定したら削除する。運用フラグは長期間残り、障害時に機能を即座に無効化するキルスイッチとして機能する。
AWS での実装パターン
SSM Parameter Store (シンプル)
import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm';
const ssm = new SSMClient({});
let cachedFlags: Record<string, boolean> | null = null;
let cacheExpiry = 0;
async function isEnabled(flagName: string): Promise<boolean> {
if (Date.now() < cacheExpiry && cachedFlags) return cachedFlags[flagName] ?? false;
const result = await ssm.send(new GetParameterCommand({
Name: '/myapp/feature-flags',
}));
cachedFlags = JSON.parse(result.Parameter!.Value!);
cacheExpiry = Date.now() + 60_000; // 1分キャッシュ
return cachedFlags![flagName] ?? false;
}
AWS AppConfig (高機能)
AppConfig はフィーチャーフラグ専用の機能を持ち、段階的ロールアウト (10% → 50% → 100%)、ユーザーセグメント、ロールバックを統合管理できる。Lambda Extension として組み込めば、Lambda 関数から低レイテンシでフラグを取得できる。
段階的ロールアウト
新機能を全ユーザーに一斉公開するのではなく、段階的に公開する。
Day 1: 社内ユーザーのみ (1%)
Day 3: ベータユーザー (10%)
Day 5: 全ユーザーの半分 (50%)
Day 7: 全ユーザー (100%)
各段階でエラー率やパフォーマンスを監視し、問題があればフラグを無効化して即座にロールバックする。デプロイのロールバックより圧倒的に速い。
フラグの技術的負債
フィーチャーフラグの最大の問題は、不要になったフラグが削除されずに残ること。フラグが増えると条件分岐が複雑化し、テストの組み合わせが爆発する。
対策
- フラグ作成時に「削除予定日」をメタデータに設定する
- CI で期限切れフラグを検出して警告する
- フラグの数に上限を設ける (例: アクティブなフラグは 20 個まで)
- リリースフラグは機能安定後 1 週間以内に削除する
フィーチャーフラグについては関連書籍でも詳しく扱われている。