Feature FlagとProgressive Deliveryで安全なリリースを実現する実践ガイド
Feature Flagを活用したProgressive Deliveryにより、本番障害リスクを低減しながらリリース頻度を向上させる方法を解説します。OpenFeatureによるベンダー非依存な実装から、Kubernetes上でのCanaryデプロイ、そしてフラグの技術負債管理まで、MLエンジニアが自チームのデプロイパイプラインを改善するための実践的な知識を提供します。
この記事でわかること
- Feature Flagの基本概念と、デプロイとリリースを分離する設計思想
- OpenFeature SDKを使ったベンダー非依存なFeature Flag実装の具体的手順
- Progressive Deliveryの3つの戦略(Canary、Blue-Green、Feature Flag)の使い分け
- Argo RolloutsによるKubernetes上での段階的ロールアウトの設定方法
- Feature Flagの技術負債を防ぐライフサイクル管理のベストプラクティス
対象読者
- 想定読者: MLモデルのデプロイや推論サービスの運用に携わるエンジニア
-
必要な前提知識:
- Pythonの基礎文法(Flask等のWebフレームワークの経験があるとベター)
- Dockerコンテナの基本的な操作
- Kubernetesの基礎概念(Pod、Deployment、Serviceが何かわかるレベル)
- CI/CDパイプラインの概念理解(GitHub Actionsなどを使ったことがあればOK)
結論・成果
Feature FlagとProgressive Deliveryを組み合わせることで、以下のような効果が報告されています。
- 障害影響範囲の縮小: 段階的ロールアウトにより、問題発生時に影響を受けるユーザーをトラフィック全体の1〜5%に抑制可能(Unleash公式ブログ)
- ロールバック時間の短縮: Feature Flagによる即座の機能無効化で、従来の再デプロイベースのロールバック(数分〜数十分)をミリ秒単位に短縮
- リリース頻度の向上: デプロイとリリースの分離により、コード変更は継続的にデプロイしつつ、機能公開のタイミングを独立して制御
Feature Flagプラットフォーム市場は2024年の$14.5億から2033年には$51.9億へ拡大が予測されており(Amplitude調査)、業界標準のプラクティスとして定着しつつあります。
Feature Flagの基本概念を理解する
Feature Flag(フィーチャーフラグ、機能フラグとも呼ばれます)は、コードの再デプロイなしにアプリケーションの動作を実行時に切り替える仕組みです。MLエンジニアにとって馴染みのある概念で例えると、学習時のハイパーパラメータをコード外の設定ファイルで管理するのと似ています。モデルの推論ロジックを変えずに、設定値だけで挙動を切り替えられるイメージです。
デプロイとリリースを分離する
Feature Flagの本質は「デプロイ(コードを本番環境に配置すること)」と「リリース(ユーザーが機能を利用できるようにすること)」の分離にあります。
従来のデプロイでは、コードを本番にデプロイした瞬間に全ユーザーが新機能を使えるようになります。これは「ビッグバンリリース」と呼ばれ、問題が発生した場合に全ユーザーが影響を受けるリスクがあります。
Feature Flagを導入すると、コードはデプロイ済みだが機能はまだ無効という状態を作れます。これにより、新機能のコードを安全に本番環境に配置し、準備ができた段階で段階的に有効化できます。
Feature Flagの分類と使い分け
Feature Flagにはいくつかの種類があり、用途によって適切なライフサイクルが異なります。Martin Fowlerの分類を基に整理します。
| フラグ種類 | 用途 | ライフサイクル | 例 |
|---|---|---|---|
| Release Flag | 未完成機能の隠蔽、段階的リリース | 短期(数日〜数週間) | 新しい推論エンドポイントの段階公開 |
| Experiment Flag | A/Bテスト、多変量テスト | 中期(数週間〜数ヶ月) | モデルv2 vs v3の精度比較 |
| Ops Flag | 運用制御、キルスイッチ | 長期(永続もあり) | 高負荷時のバッチ処理抑制 |
| Permission Flag | ユーザー権限制御 | 長期 | プレミアムユーザーのみGPU推論を許可 |
MLエンジニアにとって特に重要なのはRelease FlagとExperiment Flagです。新しいモデルバージョンのデプロイ時にRelease Flagで段階的に公開し、Experiment Flagでモデル性能を本番データで比較検証する、というワークフローが一般的です。
注意: Release Flagは短期間で削除することが前提です。「とりあえず残しておこう」とすると技術負債が蓄積します。フラグ作成時に削除予定日を設定することを強く推奨します。
OpenFeatureでベンダー非依存なFeature Flagを実装する
OpenFeatureは、CNCF(Cloud Native Computing Foundation)のインキュベーティングプロジェクトとして開発されているFeature Flagの標準仕様です。Pythonの機械学習ライブラリで例えると、scikit-learnのEstimatorインターフェースのような位置づけです。共通APIを定義することで、裏側のFeature Flagプロバイダ(LaunchDarkly、Unleash、Flagsmith等)を差し替え可能にします。
OpenFeatureのアーキテクチャ
OpenFeatureは以下の主要コンポーネントで構成されています。
| コンポーネント | 役割 | MLでの類似概念 |
|---|---|---|
| Evaluation API | フラグ値を評価するインターフェース | model.predict() |
| Provider | バックエンドとの通信を抽象化 | scikit-learnのEstimator |
| Evaluation Context | 評価時の動的コンテキスト(ユーザー情報等) | 推論時のメタデータ |
| Hooks | 評価ライフサイクルの各段階で処理を挿入 | コールバック関数 |
Python SDKでFeature Flagを実装する
OpenFeature Python SDKを使った実装例を見ていきましょう。ここでは、MLモデルの推論APIで新しいモデルバージョンへの切り替えをFeature Flagで制御するシナリオを想定します。
まず、必要なパッケージをインストールします。
# Python 3.10以上が必要
pip install openfeature-sdk openfeature-provider-flagd flask
フラグ定義ファイルを作成します。これはFlagd(OpenFeatureのリファレンス実装)が参照する設定です。
{
"flags": {
"use-new-model": {
"variants": {
"v1": false,
"v2": true
},
"state": "ENABLED",
"defaultVariant": "v1",
"targeting": {
"if": [
{
"in": ["beta", { "var": "user_segment" }]
},
"v2",
"v1"
]
}
},
"batch-size": {
"variants": {
"small": 32,
"medium": 64,
"large": 128
},
"state": "ENABLED",
"defaultVariant": "medium"
}
}
}
アプリケーションコードを実装します。
# app.py
from flask import Flask, request, jsonify
from openfeature import api
from openfeature.contrib.provider.flagd import FlagdProvider
from openfeature.evaluation_context import EvaluationContext
app = Flask(__name__)
# OpenFeature の初期化
# FlagdProvider はローカルの flagd サービスと通信する
api.set_provider(FlagdProvider())
client = api.get_client()
def predict_v1(data: dict) -> dict:
"""既存モデルの推論ロジック"""
return {"model": "v1", "prediction": 0.85}
def predict_v2(data: dict) -> dict:
"""新モデルの推論ロジック"""
return {"model": "v2", "prediction": 0.92}
@app.route("/predict", methods=["POST"])
def predict():
data = request.get_json()
user_id = data.get("user_id", "anonymous")
# Evaluation Context でユーザー情報を渡す
context = EvaluationContext(
targeting_key=user_id,
attributes={"user_segment": data.get("segment", "general")},
)
# Feature Flag でモデルバージョンを切り替え
# 第2引数はフォールバック値(flagd に接続できない場合に使用)
use_new_model = client.get_boolean_value(
"use-new-model", False, context
)
if use_new_model:
result = predict_v2(data)
else:
result = predict_v1(data)
# バッチサイズも Feature Flag で動的制御
batch_size = client.get_integer_value(
"batch-size", 64, context
)
result["batch_size"] = batch_size
return jsonify(result)
if __name__ == "__main__":
app.run(port=5000)
Flagdサービスを起動して動作確認します。
# Flagd をDockerで起動
docker run -d -p 8013:8013 \
-v $(pwd)/flags.flagd.json:/etc/flagd/flags.flagd.json \
ghcr.io/open-feature/flagd:latest start \
--uri file:/etc/flagd/flags.flagd.json
# アプリケーション起動
python app.py
# テスト: 一般ユーザー → v1モデル
curl -X POST http://localhost:5000/predict \
-H "Content-Type: application/json" \
-d '{"user_id": "user123", "segment": "general", "input": [1,2,3]}'
# => {"model": "v1", "prediction": 0.85, "batch_size": 64}
# テスト: betaユーザー → v2モデル
curl -X POST http://localhost:5000/predict \
-H "Content-Type: application/json" \
-d '{"user_id": "user456", "segment": "beta", "input": [1,2,3]}'
# => {"model": "v2", "prediction": 0.92, "batch_size": 64}
なぜOpenFeatureを選んだか:
- ベンダーロックイン回避: LaunchDarkly固有のSDKではなく、標準APIを使うことでプロバイダを後から変更できます。開発初期はFlagd(無料)で始め、スケール時にLaunchDarklyへ移行する、といった戦略が取れます
- 学習コストの最小化: OpenFeature SDKのAPIは全プロバイダで共通なので、チームメンバーが覚えるAPIは1つだけで済みます
- CNCF標準: CNCFのインキュベーティングプロジェクトであり、Kubernetes、Prometheus、Flaggerなど既存のクラウドネイティブツールチェーンとの親和性が高いです
注意: OpenFeatureはフラグ評価のAPI標準であり、フラグ管理のUI/ダッシュボードは提供しません。管理画面が必要な場合は、Unleash(OSS)やLaunchDarkly(SaaS)等のプロバイダと組み合わせて使用します。Flagdは開発環境や小規模プロジェクト向けのリファレンス実装です。
Progressive Deliveryの戦略を設計する
Progressive Delivery(段階的デリバリー)は、新しいバージョンを段階的にユーザーに公開し、メトリクスを確認しながらロールアウトを進める手法の総称です。MLエンジニアにとっては、モデルのシャドウテスト(本番トラフィックで新旧モデルを同時実行して結果を比較)やA/Bテストと同じ考え方です。
Unleash公式ブログでは、Progressive Deliveryを以下の式で定義しています(参考)。
Progressive Delivery = Progressive Deployment + Progressive Release
つまり、インフラ層でのトラフィック制御(Deployment)と、アプリケーション層での機能制御(Release)の組み合わせです。
3つの戦略の比較
| 戦略 | トラフィック制御層 | ロールバック速度 | 適用シナリオ | 複雑さ |
|---|---|---|---|---|
| Blue-Green | インフラ(ロードバランサ) | 秒単位 | インフラ変更、DB移行 | 低 |
| Canary | インフラ(Ingress/Service Mesh) | 秒〜分 | パフォーマンス影響のある変更 | 中 |
| Feature Flag | アプリケーション(コード内) | ミリ秒 | 機能追加、UI変更、モデル切替 | 低〜中 |
どの戦略をいつ使うべきか:
- Blue-Green: インフラレベルの変更(Kubernetesバージョンアップ、DB設定変更)に向いています。「全か無」のスイッチなので、段階的なロールアウトには不向きです
- Canary: パフォーマンスやリソース消費に影響する変更に向いています。インフラ層でトラフィック配分を制御するため、アプリケーションコードの変更が不要です
- Feature Flag: 機能レベルの変更に最適です。ユーザー属性に基づいた細かいターゲティング(例: 特定の組織のユーザーのみ新モデルを使用)が可能です
実際のプロジェクトでは、これらを組み合わせて使うのが一般的です。例えば、Canaryデプロイで新バージョンのPodを5%だけ配置し、その中でFeature Flagにより特定ユーザーにのみ新機能を有効化する、といった構成です。
Argo RolloutsでKubernetes上のCanaryデプロイを実装する
Argo Rolloutsは、Kubernetes上でProgressive Deliveryを実現するコントローラです。標準のDeploymentリソースを拡張したRolloutリソースを使い、Canaryデプロイやメトリクスベースの自動昇格/ロールバックを提供します。
以下は、ML推論サービスのCanaryデプロイ設定例です。
# rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: ml-inference-service
spec:
replicas: 10
revisionHistoryLimit: 3
selector:
matchLabels:
app: ml-inference
strategy:
canary:
# 段階的にトラフィックを増加
steps:
- setWeight: 5 # 5%のトラフィックを新バージョンに
- pause:
duration: 5m # 5分間メトリクスを観測
- analysis:
templates:
- templateName: success-rate-check
- setWeight: 20 # 問題なければ20%に拡大
- pause:
duration: 10m
- analysis:
templates:
- templateName: success-rate-check
- setWeight: 50 # 50%に拡大
- pause:
duration: 10m
- setWeight: 100 # 全トラフィック切替
# 失敗時の自動ロールバック
abortScaleDownDelaySeconds: 30
template:
metadata:
labels:
app: ml-inference
spec:
containers:
- name: inference
image: ml-inference:v2
ports:
- containerPort: 8080
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "4Gi"
nvidia.com/gpu: 1
---
# メトリクスベースの自動分析テンプレート
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate-check
spec:
metrics:
- name: success-rate
# Prometheus からリクエスト成功率を取得
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{
app="ml-inference",
status=~"2.."
}[5m])) /
sum(rate(http_requests_total{
app="ml-inference"
}[5m])) * 100
# 成功率が99%を下回ったら自動ロールバック
successCondition: result[0] >= 99
failureLimit: 3
interval: 60s
# Argo Rollouts のインストール(Kubernetes クラスタに適用)
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts \
-f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
# Rollout の適用
kubectl apply -f rollout.yaml
# ロールアウト状況の確認
kubectl argo rollouts get rollout ml-inference-service --watch
# 手動で次のステップに進める場合
kubectl argo rollouts promote ml-inference-service
# 問題発生時の手動ロールバック
kubectl argo rollouts abort ml-inference-service
なぜArgo Rolloutsを選んだか:
- GitOps親和性: Argo CDと組み合わせることで、Gitリポジトリの変更をトリガーに自動Canaryデプロイが実現できます
- メトリクスベースの自動判定: Prometheus、Datadog、New Relic等のメトリクスプロバイダと連携し、人間の判断なしにロールアウトの昇格/ロールバックを自動化できます
-
Kubernetes ネイティブ: CRD(Custom Resource Definition)として実装されているため、
kubectlで操作でき、既存のKubernetesワークフローに自然に統合できます
注意: Argo Rolloutsを使うにはKubernetesクラスタが必要です。マネージドMLプラットフォーム(SageMaker、Vertex AI等)を使っている場合は、プラットフォーム固有のCanaryデプロイ機能を利用する方が運用負荷が低くなります。Argo Rolloutsはセルフホストの推論サービスに向いています。
Feature FlagとCanaryデプロイの組み合わせパターン
実際のMLシステムでは、Feature FlagとCanaryデプロイを組み合わせた「2段構え」の安全策が有効です。
- インフラ層(Argo Rollouts): 新バージョンのPodを5%→20%→50%→100%と段階的にデプロイ。レイテンシやエラー率をメトリクスで自動監視
- アプリケーション層(Feature Flag): デプロイされた新バージョンのPod内で、Feature Flagにより特定ユーザーセグメントのみ新機能を有効化
この構成では、仮にインフラ層のCanaryが100%に達しても、Feature Flagがまだ全ユーザーにはONになっていないため、「新しいPodは全台デプロイ済みだが、新機能は10%のユーザーにしか見えていない」という状態を作れます。
よくある間違い: 最初からCanaryデプロイとFeature Flagの両方を導入しようとすると、複雑さが一気に増します。まずはFeature Flagのみで段階的リリースを始め、インフラ変更時のリスクが課題になった段階でCanaryデプロイを追加する、という順序を推奨します。
Feature Flagの技術負債を管理する
Feature Flagは強力なツールですが、適切に管理しないと深刻な技術負債を生みます。LaunchDarklyの公式ドキュメント(参考)では、「フラグの保守を怠ると、コードの複雑化、データの肥大化、緊急時の対応遅延」が発生すると警告しています。
Uberは自動リファクタリングツール「Piranha」を開発し、約2,000個の不要フラグを自動削除した事例を公開しています。2025年以降はGitHub Copilot Agent Tasksを使ったAI駆動のフラグクリーンアップも登場しており(Unleash公式ブログ)、自動化のハードルは下がっています。
フラグのライフサイクル管理
LaunchDarklyのガイドに基づくフラグのライフサイクルは以下の4段階です。
技術負債を防ぐ7つのプラクティス
以下はLaunchDarklyの公式ガイドを基に整理した実践的なプラクティスです。
1. 命名規則を統一する
意味不明なフラグ名(例: FF123_do_not_delete_this_72)は、開発者が入れ替わった際に判断不能になります。
# 悪い例
flag_name = "ff_123"
flag_name = "new_feature_test_v2_final"
# 良い例: <チーム>.<機能>.<種類> の形式
flag_name = "ml-team.model-v3-inference.release"
flag_name = "ml-team.batch-size-experiment.experiment"
2. 削除予定日をフラグ作成時に設定する
フラグを作成するときに「いつ削除するか」も同時に決めます。Release Flagの場合、ロールアウト完了予定日の2週間後を目安にします。
3. タスク完了の定義にフラグ削除を含める
スプリントのDone(完了)定義に「関連するFeature Flagの削除」を含めます。機能が完全にロールアウトされたらフラグは不要なので、コードからフラグ参照を削除し、フラグをアーカイブします。
4. フラグのスコープを最小化する
1つのフラグで複数の機能を制御しないことが重要です。例えば、新しいダッシュボードに3つのウィジェットがある場合、メインの表示フラグ1つ + 各ウィジェットの制御フラグ3つの計4つに分割します。
5. 永続フラグを明示する
運用制御用のキルスイッチなど、削除予定のないフラグは作成時に「永続フラグ」として明示的にマークします。これにより、定期レビュー時に「このフラグは削除対象か?」という判断が不要になります。
6. 月次クリーンアップサイクルを設ける
月次または四半期ごとに不要フラグの棚卸しを実施します。LaunchDarklyのFlag Healthメトリクスでは、「Stale Flag比率」を可視化できます。
7. 削除用PRをフラグ作成時に作成する
フラグを追加するPRとセットで、フラグ削除用のPR(ドラフト)も作成しておきます。ロールアウト完了後にドラフトPRを完成させてマージするだけで済むため、クリーンアップの心理的ハードルが下がります。
トレードオフ: 厳格すぎるフラグ管理ルールは開発速度を低下させます。小規模チーム(5名以下)では命名規則と削除予定日の設定だけで十分です。フラグ数が50を超えたタイミングで、タグ付けやCode Referencesの導入を検討しましょう。
よくある問題と解決方法
| 問題 | 原因 | 解決方法 |
|---|---|---|
| フラグが100個を超えて管理不能 | 削除予定日を設定していない | 作成時に削除予定日を必須化し、期限切れフラグを自動検出 |
| 本番でフラグを切り替えたら予期しないエラー | フラグ間の依存関係を把握していない | フラグの依存関係を文書化し、切替前にテスト環境で検証 |
| 新メンバーがフラグの目的を理解できない | 命名が曖昧で説明文がない | 命名規則の統一と説明文の必須化 |
| フラグ削除後に同じキーで新フラグを作成して障害 | アーカイブせずに削除した | 削除ではなくアーカイブを使い、キーの再利用を避ける |
| フラグ評価のレイテンシが無視できなくなった | フラグ評価が同期的にリモートAPIを呼んでいる | SDKのローカルキャッシュを使用し、バックグラウンドで同期 |
2026年のFeature Flagエコシステムの動向を把握する
2026年現在、Feature Flagエコシステムは大きな変化を迎えています。ここでは、MLエンジニアが押さえておくべき動向を紹介します。
Datadog Feature Flags の登場
2026年2月、DatadogがオブザーバビリティプラットフォームにネイティブのFeature Flags機能を追加しました(公式プレスリリース)。これにより、Feature Flagの状態とAPM(Application Performance Monitoring)のメトリクスを統合ダッシュボードで確認できるようになりました。
「このフラグをONにした直後にレイテンシが増加した」という因果関係を、単一のツールで把握できるようになった点が重要です。
AI駆動のProgressive Delivery
Feature Flag管理へのAI活用も進んでいます。具体的には以下のような機能が登場しています(azati.ai調査)。
- リリースリスク予測: 過去のデプロイ履歴とコード変更量から、新リリースの障害リスクをスコアリング
- 自動ロールバック判定: メトリクス異常を検知した場合に、人間の判断を待たずにフラグをOFFに自動切替
- 不要フラグの自動検出: コードベースのスキャンとフラグ評価ログの分析から、削除候補のフラグを自動提案
主要ツールの比較
2026年時点の主要Feature Flagツールを比較します。
| ツール | 種類 | OpenFeature対応 | 特徴 | 適用規模 |
|---|---|---|---|---|
| Flagd | OSS | ネイティブ | OpenFeatureリファレンス実装、開発環境向け | 小規模 |
| Unleash | OSS/SaaS | 対応 | セルフホスト可能、コミュニティ活発 | 中〜大 |
| Flagsmith | OSS/SaaS | 対応 | OpenFeature創設メンバー、ML機能追加中 | 中〜大 |
| LaunchDarkly | SaaS | 対応 | 業界リーダー、1日数兆回のフラグ評価実績 | 大規模 |
| Statsig | SaaS | 対応 | AI/ML組み込み、実験機能に強い | 中〜大 |
| Datadog Feature Flags | SaaS | 未確認 | オブザーバビリティ統合、2026年2月発表 | 大規模 |
制約条件: OSSツール(Flagd、Unleash、Flagsmith)はセルフホストの運用負荷がかかります。MLエンジニアがインフラ管理も担当する小規模チームでは、SaaS型のツールを選ぶ方が実装に集中できます。一方、データの外部送信に制約がある環境(社内ポリシーや規制産業)では、OSSのセルフホストが唯一の選択肢になります。
まとめと次のステップ
まとめ:
- Feature Flagの本質はデプロイとリリースの分離にあり、コード変更の安全性と公開タイミングの柔軟性を両立できます
- OpenFeatureはCNCFインキュベーティングプロジェクトとして標準化が進んでおり、ベンダーロックインなしでFeature Flagを導入できます
- Progressive Deliveryでは**Canary(インフラ層)とFeature Flag(アプリ層)**を組み合わせた2段構えが効果的です
- Feature Flagの技術負債は放置すると深刻化するため、フラグ作成時に削除予定日を設定し、月次レビューで棚卸しすることが重要です
- 2026年はDatadogのFeature Flags発表やAI駆動のProgressive Deliveryなど、オブザーバビリティとの統合が加速しています
次にやるべきこと:
- まずはOpenFeature + Flagdで小さく始める: 開発環境でフラグ評価の基本フローを体験しましょう。Docker環境があれば10分で動かせます
- 1つのRelease Flagから運用を開始: いきなり全機能にフラグを適用せず、次のリリースの1機能だけにFeature Flagを導入して運用フローを検証しましょう
- フラグ管理ルールをチームで合意: 命名規則と削除予定日の設定ルールを最低限決めてから運用を拡大しましょう
参考
- OpenFeature公式ドキュメント
- OpenFeature Python SDK チュートリアル
- OpenFeature Specification (GitHub)
- Progressive Delivery with Feature Flags - Unleash
- Argo Rollouts公式ドキュメント
- LaunchDarkly: Reducing technical debt from feature flags
- Datadog Feature Flags発表
- AI-Powered Progressive Delivery 2026 - azati.ai
- Top Feature Flag Solutions 2026 - Amplitude
- Tired of Cleaning Up Stale Feature Flags? Let AI Do the Work! - Unleash
注意: この記事はAI(Claude Code)により自動生成されました。内容の正確性については複数の情報源で検証していますが、実際の利用時は公式ドキュメントもご確認ください。