はじめに
生成AIによる開発が一般的になり、実装そのものの速度は大きく上がってきました。
それなりにAIを活用できている開発組織においては人間がゼロからコードを書くというより、AIに実装させ、人間が方針を決め、レビューし、必要に応じて修正する、という開発スタイルが一般的になってきているのではないでしょうか。
一方で、コードを書く速度が上がったからといって、ソフトウェアのリスクが消えるわけではありません。
むしろ、変更量が増えることで、レビュー、QA、リリース判定、障害対応といった「確認する側」の工程が相対的にボトルネックになりやすくなっています。これは確認側の口数が、実装する側に比べて生成AIによる恩恵を受けづらいことが原因の一つだと考えられます。
これまで人間が書いていたコードをAIが生成するようになったことでリスクが増えた、と言われることがあります。しかし、本質的には、人間が書いてもAIが書いてもバグは入り得ます。重要なのは、誰がコードを書いたかではなく、その変更をどのように安全に本番へ届けるかです。
これまで直接コードを書いていた人が、いわゆる管理職のように、直接コードを書くことがなくなって成果物のチェック役に回ったとも言えます。
たとえば、DORAでは、ソフトウェアデリバリーのパフォーマンスを見る指標として、デプロイ頻度、変更のリードタイム、変更失敗率、復旧時間などが扱われています。つまり、単にリリース頻度を上げるだけではなく、変更が失敗したときの影響や復旧も含めて考える必要があります。
言い換えれば、確認に工数をかける度合いとリリースの頻度などの度合いを鑑みて、リスクをどのようにコントロールするかが重要になってきます。
この記事では、そもそも100%の確認は不可能であるという前提に立ちます。
そのうえで、リリースを高頻度にし、1回あたりの変更を小さくし、影響範囲を限定し、問題が起きたらすぐ止められる仕組みとしてFeatureFlagを考えていきます。
特にMartin Fowlerの記事にあるFeature Toggleの考え方を参考にしながら、AI時代のリリースリスク低減にFeatureFlagをどう活用できるかを整理します。Feature Toggleは、ユーザーに新機能を速く、かつ安全に届けるためのパターンとして説明されています。
1. AI時代にリリースリスクが問題になる理由
AIを使うことで、実装速度は上がります。
これまで数日かかっていた実装が数時間で終わることもありますし、細かい修正やリファクタリングもAIに任せやすくなりました。結果として、1人のエンジニアが扱える変更量は増えていきます。
しかし、AIが高速化しているのは現状では実装工程に集中しています。
仕様が正しいか、既存機能に影響しないか、本番データで問題が起きないか、ユーザーが期待通りに使えるか、障害時にすぐ戻せるか、といった点は自動的には解決されません。
むしろ、変更量が増えるほど、これらの項目を確認すべき対象自体も増えます。
たとえば、AIによって以下のような変更が短時間で作れるようになります。
- 新しい画面の追加
- 既存UIの刷新
- APIレスポンス構造の変更
- DBアクセス処理の変更
- 外部API連携の追加
- バッチ処理の最適化
- 権限制御の修正
- リファクタリング
これらは開発効率の面では非常に強力です。
しかし、変更が本番に出た瞬間、そこには必ずリスクがあります。
Google SRE WorkbookのCanary Releaseの章でも、変更は実世界の入力やトラフィックにさらされるまで未知のリスクを持つため、小さな範囲に出して安全性を確認する考え方が説明されています。
AI時代のリスクは、「AIが間違えること」そのものだけではありません。より大きな問題は、AIによって増えた変更量を、従来のリリースプロセスで扱いきれなくなることです。
人間がすべての差分を細かく読み、QAがすべてのパターンを確認し、問題がないと判断してから本番に出す。このやり方は、変更量が少ないうちは機能します。
しかし、AIによって実装スピードが上がると、確認工程だけが追いつかなくなります。
その結果、次のどちらかに偏りやすくなります。
- 1つ目は、確認がボトルネックになり、リリースできない状態です。
- 2つ目は、確認が薄くなり、リスクが高いまま本番に出てしまう状態です。
1つ目はAIで実装は終わっているのに、レビュー待ち、QA待ち、リリース判定待ちが積み上がり、結局ユーザーに価値が届かない状態です。
2つ目はAIによって変更が増えたにもかかわらず、従来と同じ感覚でリリースしてしまい、想定外の障害や問い合わせ増加につながる状態です。
どちらも望ましくありません。必要なのは、確認を無限に厚くすることではなく、変更を小さく出し、影響範囲を制御し、問題があればすぐ止められる構造です。
AI時代に必要なのは、AIが書いたコードを人間が全部読んで安心することではなく、変更を安全に本番へ流すための仕組みになりました。
2. 100%確認してからリリースすることの限界
理想を言えば、すべてのリリース前にすべてのリスクを確認できるのが一番安全です。
しかし、現実にはそれはほぼ不可能です。これはAIの登場以前から存在していた問題ですが、AIによって変更量が増えることで、より顕著になっています。
ソフトウェアには、事前に確認しきれない要素が多くあります。
もちろん、テストやレビューが不要という話ではありません。
むしろ、AI時代においてもテストやレビューは重要です。ただし、それらを「リスクをゼロにするための手段」と考えるのは無理があります。リスクはゼロにすることはできません。
できるのは、リスクを見つけやすくし、影響範囲を小さくし、問題が起きたときに早く止められるようにすることです。言い換えるとリスクをコントロールすることです。
ここで重要になるのが、リリース単位の小ささです。
1回のリリースに大量の変更が含まれていると、問題が起きたときに原因を特定しづらくなる、問題が大きくなる、復旧に時間がかかる、ということが起きやすくなります。
たとえば、以下のようなリリースがあったとします。
- 予約画面のUI刷新
- APIレスポンス変更
- 権限制御の変更
- DBカラム追加
- 通知処理の変更
- 外部サービス連携の追加
この状態で本番障害が起きた場合、どの変更が原因なのかをすぐに判断するのは難しくなります。
一方で、変更が小さく、公開範囲も限定されていれば、問題の切り分けはかなり楽になります。
リリース頻度が低い組織では、1回あたりのリリースが大きくなりがちです。
「安全のためにリリース頻度を下げる」という判断は、一見すると正しそうに見えます。しかし、リリース頻度が下がることで、1回あたりの変更量が増え、結果的にリリースのリスクが高くなることがあります。
AI時代により重要となる戦略として、安全なリリースを行うためには壊れる可能性を前提に、壊れても影響を限定でき、すぐ戻せるリリースの仕組みを用意する必要があります。
そのためには、以下のような考え方が必要になります。
- 1回の変更を小さくする
- 変更を早くmain/masterに統合する
- デプロイとリリースを分離する
- 最初から全ユーザーに出さない
- 問題が起きたら即座に止められるようにする
- リリース後の状態を観測する
FeatureFlagは、この考え方を実現するための手段の一つとして非常に有効です。
3. FeatureFlagとは何か
FeatureFlagとは、コードを変更せずに機能の有効・無効を切り替える仕組みです。大体2009年ごろから使われ始めた考え方で、Flickrの技術ブログなどで近しい概念が登場したようです。
Flipping Out | code.flickr.com
その後Martin Fowlerのブログによって概念が整理され、分類の整理と業界への浸透が進みました。
Feature Toggle、Feature Flag、Feature Switchなど、いくつか呼び方はありますが、基本的には同じ考え方です。
Martin FowlerのFeature Toggleの記事では、Feature Toggleはシステムの振る舞いをコード変更なしで変えるための強力な手法として説明されています。ただし同時に、Toggleは複雑性を持ち込むため、用途ごとの分類を考慮することが重要だとも述べられています。
非常に単純な例で言えば、以下のようなものです。
if ($featureFlag->enabled('new_reservation_flow', $user)) {
return $this->newReservationFlow($request);
}
return $this->oldReservationFlow($request);
フロントエンドであれば、次のような形になります。
if (flags.newReservationFlow) {
return <NewReservationFlow />;
}
return <OldReservationFlow />;
これだけを見ると、単なるif文ですが、本質は、デプロイとリリースを分離することにあります。
FeatureFlagがない場合、基本的にはコードを本番環境にデプロイした瞬間に、全ユーザーへ機能が公開されます。
merge → deploy → 全ユーザーに公開
一方でFeatureFlagがある場合、コードは本番環境にデプロイされているが、まだユーザーには公開されていない、という状態を作れます。
merge → deploy → flag OFF → 社内ON → 一部ユーザーON → 全体ON
この違いは非常に大きいです。
コードを本番に置くことと、ユーザーに機能を見せることを分けられるからです。
これにより、たとえば以下のようなことが可能になります。
- 本番環境にコードを置いたまま、ユーザーには非公開にする
- 社内ユーザーだけ新機能を使えるようにする
- 特定のβユーザーだけに公開する
- 5%、25%、50%、100%のユーザーを対象にするように段階公開する
- 問題が起きたらFeatureFlagをOFFにして機能を止める
- ビジネス上の公開タイミングとデプロイタイミングを分ける
つまりFeatureFlagは、単なる実装テクニックではなく、リリース制御の仕組みです。
AI時代においては、実装速度が上がるぶん、この「安全に出すための制御」がより重要になります。
また、FeatureFlagは自作もできますが、近年はOpenFeatureのように標準化の動きもあります。OpenFeatureは、特定ベンダーに依存しないFeature FlaggingのAPI仕様を提供するプロジェクトで、Feature Flag管理ツールや自社実装を共通インターフェースで扱うことを目的としています。
4. FeatureFlagで低減できるリスク
影響範囲を限定できる
いきなり全ユーザーに公開しなくてよくなります。
たとえば、新しい予約画面を出す場合でも、最初から全体公開する必要はありません。
1. 開発者だけON
2. QA担当者だけON
3. 社内ユーザーだけON
4. 特定のテスト店舗だけON
5. βユーザーだけON
6. 5%のユーザーだけON
7. 25%、50%、100%と拡大
問題が起きても、影響範囲はその時点の公開対象に限定されます。
「全員に出してから気づく」のではなく、「小さく出して気づく」状態を作れます。
問題が起きたときにすぐ止められる
本番障害時に、コードのrevertや再デプロイを待つのは重いです。
- CI/CDを待つ必要がある
- デプロイに時間がかかる
- DB変更と整合しない場合がある
- キャッシュやキューに影響が残る
- 緊急対応中に追加のミスが起きやすい
FeatureFlagがあれば、コードを戻さずに機能だけをOFFにできます。
特に、次のような機能では有効です。
- 新しいUI
- 重い集計処理
- 外部API連携
- 非同期ジョブ
- AIによる提案機能
- 新しい検索処理
たとえば外部API連携が不安定になった場合、その連携だけを止められれば、サービス全体への影響を抑えられます。
この用途のFeatureFlagは、リリース制御というよりkill switchに近いです。
デプロイとリリースを分離できる
未公開の機能でも、flag OFFの状態でmainに統合できます。
つまり、コードは早く統合し、公開タイミングだけを後で制御できます。
FeatureFlagがない場合、未完成の機能はmainに入れづらくなります。その結果、長期間のfeature branchが生まれます。
長いブランチは、次の問題を起こします。
- コンフリクトが増える
- レビュー差分が大きくなる
- 結合時の不具合が増える
- リリース単位が大きくなる
FeatureFlagを使えば、変更を小さく統合し続けながら、公開だけを制御できます。
AIで実装速度が上がるほど、差分を長くブランチに閉じ込めるリスクは大きくなります。
早く統合し、小さくデプロイし、公開はFeatureFlagで制御する。
この流れは、AI時代の開発フローと相性がよいです。
段階的に学習できる
新機能は、作った時点では仮説です。特にWEB開発などはこの不確実性に向き合うためにアジャイル開発などさまざまな手法が生まれてきました。
ユーザーが使うか、問い合わせが増えないか、性能に問題がないかは、実際に出さないとわからないことがあります。
FeatureFlagを使えば、小さく出して観測できます。
- フラグONのユーザーだけエラー率が高くないか
- 新UIの利用率は想定通りか
- 問い合わせが増えていないか
- レイテンシが悪化していないか
- CVが下がっていないか
- 想定外の操作ログが出ていないか
一気に全体公開するのではなく、観測しながら公開範囲を広げる。
FeatureFlagは、安全装置であり、学習のための仕組みでもあります。
5. FeatureFlagの種類
FeatureFlagは、用途によって性質が違います。
Martin Fowlerの記事では、Feature Toggleを複数の種類に分けて考えています。
代表的な分類は次の4つです。
- Release Toggle
- Experiment Toggle
- Ops Toggle
- Permission Toggle
すべてを同じON/OFF設定として扱うと、運用が破綻しやすくなります。
Release Toggle
Release Toggleは、未公開の機能を本番コードに含めつつ、ユーザーにはまだ見せないためのフラグです。
目的は、デプロイとリリースの分離です。
コードはmainに統合し、本番にもデプロイする。しかし、FeatureFlagがOFFなのでユーザーには見えない。
その後、社内確認や段階公開を経て、全体公開します。Release Toggleは基本的に一時的なものです。
全体公開が終わったら、古い実装とフラグ分岐を削除します。
Experiment Toggle
Experiment Toggleは、A/Bテストや効果検証のためのフラグです。
ボタン文言を変えるとCVが上がるのか。
レイアウトを変えると離脱率が下がるのか。
こうした仮説検証に使います。
Experiment Toggleでは、ON/OFFだけでは不十分です。
どのユーザーにどのバリエーションを出したか、その結果どうなったかを計測する必要があります。
そのため、ログ設計や分析基盤とセットで扱います。
Ops Toggle
Ops Toggleは、運用や障害対応のためのフラグです。
例です。
外部APIが不安定なときに連携を止める。
負荷が高いときに重い集計処理を止める。
AI提案機能が不安定なときに一時停止する。
こうした用途で使います。
Ops Toggleは、Release Toggleと違って長期的に残る場合があります。
障害対応や負荷制御のスイッチとして価値があるからです。
ただし、長く残すなら運用ルールが必要です。
- 誰がOFFにできるのか
- OFFにすると何が止まるのか
- OFF時にユーザーにはどう見えるのか
- 復旧時に誰がONに戻すのか
ここが曖昧なOps Toggleは、障害時に混乱を生みます。
Permission Toggle
Permission Toggleは、特定のユーザー、組織、契約プラン、権限に応じて機能を出し分けるためのフラグです。
βユーザーだけに新機能を出す。
特定プランだけに高度な機能を出す。
管理者だけに新しい設定画面を出す。
こうした用途で使います。
ただし、Permission Toggleを権限制御そのものとして扱うのは危険です。
フロントエンドでボタンを隠しても、APIを直接叩けるなら制御できていません。
課金、権限、データアクセスに関わるものは、必ずバックエンドで認可します。
Permission Toggleは「見せ方の制御」であり、セキュリティ上の認可とは分けて考えるべきです。
種類ごとに寿命が違う
FeatureFlagは、種類ごとに寿命が違います。
Release Toggleは短命にします。
Experiment Toggleも、検証が終われば削除するか正式実装に統合します。
Ops ToggleやPermission Toggleは、長く残る場合があります。
この違いを無視すると、削除すべきフラグが残り続けたり、残すべき運用スイッチが雑に消されたりします。
そのため、作成時点で種類を明確にします。
たとえば以下のような形です。
name: reservation_calendar_v2
type: release
owner: reservation-team
created_at: 2026-05-25
expected_cleanup_date: 2026-06-30
description: 新しい予約カレンダー画面への切り替え
FeatureFlagは、作ることよりも、管理し、消すことのほうが重要です。
自分たちの場合
上記の分類はあくまで一例です。自分たちの開発するアプリケーションの場合、どのようなFeatureFlagが必要かを考える必要があります。
自分たちの場合は、Release ToggleとExperiment Toggleが重要度が高そうだったため、テナントごとのIDに紐づく形で、ON/OFFを切り替えられるようなFeatureFlagの仕組みを実装しました。
一旦シンプルなフラグ実装を選択し、必要度が上がればUnleashなどの成熟したツールの導入も検討する、という方針で進めています。
6. FeatureFlagを安全に運用するための設計
FeatureFlagは、入れるだけでは安全になりません。
雑に導入すると、分岐が増え、状態が複雑になり、誰も消せないフラグが残りかねないので設計と運用が必要です。
フラグの単位は「独立して止めたい単位」にする
フラグの粒度は、粗すぎても細かすぎても問題です。
粗すぎると、一部だけ止めたいときに止められません。細かすぎると、管理できません。
たとえば、予約機能全体を1つのフラグにするとします。
reservation_renewal
この中に、カレンダー、プラン選択、オプション選択、確認画面、通知処理まで含めると、新しいカレンダーだけ止めたい場合に困ります。
その場合は、次のように分けたほうが扱いやすくなります。
reservation_calendar_v2
reservation_plan_selector_v2
reservation_option_selector_v2
reservation_confirm_screen_v2
reservation_notification_v2
ただ、細かすぎると管理が煩雑になります。自分たちの場合は障害じの独立単位でフラグを切る運用を選択しました。つまり基準は、障害時に独立して止めたいかどうかです。
FeatureFlagは機能単位ではなく、リスク単位で設計するのがよいと考えています。
フラグ自体の状態と、機能の公開状態を分ける
active や enabled に複数の意味を持たせると混乱します。
たとえば、enabled = true は何を意味するのでしょうか。
- フラグ管理対象として有効
- 機能が全ユーザーに公開されている
- デフォルトでON
- 一部ユーザーだけON
- kill switchが解除されている
- 正式リリース済み
これらが混ざると、運用時に判断できなくなります。
そのため、管理状態と評価結果を分けます。
FeatureFlagの管理状態:
- active
- archived
機能の評価結果:
- enabled
- disabled
公開ルール:
- default off
- internal users only
- beta users only
- percentage rollout
- all users
「フラグがactiveである」ことと、「ユーザーに機能が公開されている」ことは別です。
activeなフラグでも、対象ユーザーへの評価結果はdisabledかもしれません。
正式リリース済みで全員に公開されているなら、フラグ分岐自体を消す判断も必要です。
フラグには所有者と削除期限を持たせる
FeatureFlagは、作った瞬間から負債になる可能性があります。
リスクを下げるために必要な負債ですが、使い終わったあとも残ると保守性を下げます。
最低限、次の情報は持たせたいです。
name
type
owner
created_at
expected_cleanup_date
related_issue
description
rollout_status
特に重要なのは、ownerとexpected_cleanup_dateです。
誰が責任を持つのか。
いつ削除する予定なのか。
これがないフラグは、誰も消せなくなります。
Release Toggleであれば、作成時点で削除用Issueを作るのがよいです。
1. FeatureFlagを作る
2. flag OFFで実装をmainに入れる
3. 社内・一部ユーザーに段階公開する
4. 全体公開する
5. 旧実装とFeatureFlag分岐を削除する
FeatureFlagはリスクを減らす仕組みですが、削除されないFeatureFlagは将来のリスクになります。
監視・ログ・アラートとセットで運用する
段階公開しても、状態を観測できなければ意味がありません。
5%に公開しても、その5%で何が起きているかわからなければ、ただの遅い全体公開です。
FeatureFlagを使うなら、次の情報を見られるようにします。
- フラグON/OFFごとのエラー率
- フラグON/OFFごとのレイテンシ
- 対象機能の利用率
- 問い合わせ数
- CV
- 外部API失敗率
- 例外ログ
- 対象ユーザー数
- 段階公開の履歴
特に重要なのは、ONのユーザーとOFFのユーザーを比較できることです。
ONのユーザーだけエラー率が高いなら、その機能が原因である可能性が高くなります。
また、停止基準も事前に決めます。
- エラー率が通常時の2倍を超えたらOFF
- 外部API失敗率が10%を超えたらOFF
- 問い合わせが一定数を超えたらロールアウト停止
- レイテンシp95が基準値を超えたら段階公開を止める
FeatureFlagは、観測とセットで初めてリスク低減になります。
7. FeatureFlag導入時のアンチパターン
FeatureFlagは強力ですが、誤用すると逆にリスクになります。
代表的なアンチパターンを整理します。
何でもFeatureFlagにする
すべての変更にFeatureFlagを付けると管理不能になります。
軽微な文言修正、スタイル調整、小さなリファクタリングまでフラグ化する必要はありません。
FeatureFlagを使うべきなのは、次のような変更です。
- ユーザー影響が大きい
- 段階公開したい
- 問題時に個別で止めたい
- 戻すのが難しい
- 外部APIに依存している
- 性能影響が読みにくい
- 公開タイミングを制御したい
- βユーザーや特定顧客に限定公開したい
FeatureFlagは、何でも隠すための仕組みではありません。
リスクを制御するための仕組みです。
フラグが削除されない
FeatureFlagの典型的な問題は、削除されないことです。
一時的なつもりで作ったフラグが、いつの間にか誰も意味を知らない状態で残り続けます。
if ($featureFlag->enabled('new_flow')) {
// 新しい処理
} else {
// 古い処理
}
この分岐が何ヶ月も残ると、誰も安全に触れなくなります。
フラグが残ることで、次の問題が起きます。
- コードが読みにくくなる
- テストパターンが増える
- どちらの分岐が使われているかわからなくなる
- 古い実装を消せなくなる
- 新しい変更がさらに複雑になる
- 障害時の切り分けが難しくなる
Release Toggleは、全体公開が完了したら削除します。
FeatureFlagは、作るときに削除まで計画するべきです。
フラグの意味が曖昧
enabled_new_feature や use_v2 のような雑な命名は、時間が経つと意味がわからなくなります。
いつ消してよいのか。何のためのフラグなのかがわからないフラグは危険です。
対策としては、名前だけでなく、説明も持たせます。
FeatureFlagは運用で使うものです。
人間が読んで理解できることが重要です。
フロントエンドだけで制御する
UIの出し分けだけなら、フロントエンドのFeatureFlagで十分な場合もあります。
しかし、権限、課金、データ更新、外部API実行に関わるものをフロントエンドだけで制御してはいけません。
フロントエンドでボタンを非表示にしても、APIを直接叩けるなら制御できていません。
if (flags.advancedReport) {
return <AdvancedReportButton />;
}
バックエンド側でも必ず認可します。
if (! $user->canUseAdvancedReport()) {
abort(403);
}
FeatureFlagは権限制御の代替ではありません。
特にPermission Toggleでは、プロダクト上の出し分けとセキュリティ上の認可を分けて考える必要があります。
DB変更をFeatureFlagだけで安全にしようとする
FeatureFlagは万能ではありません。
特にDB変更を伴う場合は注意が必要です。
FeatureFlagで新機能をOFFにできても、互換性のないDB変更は簡単には戻せません。
たとえば、既存カラムを削除したあとに問題が起きても、FeatureFlagをOFFにするだけでは復旧できません。
DB変更は段階的に行います。
1. 新カラムを追加する
2. 旧コードでも新コードでも動く状態にする
3. 必要であれば新旧両方に書き込む
4. 読み取りを新カラムに切り替える
5. 問題がないことを確認する
6. 古いカラムや古い処理を削除する
FeatureFlagは、切り替えポイントの制御には有効です。
しかし、互換性のないDB変更を安全にしてくれるわけではありません。
FeatureFlagはリリース制御の仕組みであり、すべての設計ミスを吸収する魔法ではありません。
8. まとめ
- AIによって、ソフトウェア開発の速度は上がる
- AIが生成したコードであっても、人間が書いたコードであっても、本番で問題は起こり得ます。
- AIによって開発速度が上がるため、問題の発生自体も加速する
- 実装速度はAIの恩恵を受けているが、確認作業は恩恵を受けづらく、限界がある
- 元より、全てのテストは不可能だったのでテスト以外でのリスクコントロールが重要になる
FeatureFlagを使うことで、次のようなリリースが可能。
- デプロイとリリースを分離する
- いきなり全ユーザーに公開しない
- 社内ユーザーやβユーザーだけに公開する
- 段階的にロールアウトする
- 問題が起きたらすぐOFFにする
- フラグON/OFFごとに状態を観測する
- リリース後に学習しながら改善する
FeatureFlagは、AI時代における安全なリリースのための重要な仕組み。 ただし、FeatureFlag自体にも設計と運用が必要
- フラグの種類を明確にする
- Release Toggleは短命にする
- Ops ToggleやPermission Toggleは運用ルールを明確にする
- ownerと削除期限を持たせる
- フラグの単位はリスク単位で設計する
- 監視やログとセットで運用する
- DB変更の安全性は別途設計する
つまり、テストの限界を超えた部分についてはリスクをコントロールできるリリースフローの設計が重要で、FeatureFlagはそのための現実的で強力な手段のひとつになり得る。
- AI時代に必要なのは、AIが書いたコードを人間がすべて読んで安心することではない
- 小さく出し、観測し、問題があればすぐ止められる構造を作ること
AIによって実装が速くなる時代だからこそ、リリースを安全にするための設計に投資する価値がある。
