段階的変更(Incremental Change):Feature Toggle・Blue-Green・Canary・Dark Launch
なぜ大きなリリースは危ないのか。Feature Toggle / Blue-Green / Canary / Dark Launch の4パターンを比較し、Fitness Function との接続を整理する
なぜ大きなリリースは危ないか
「変更の可逆性」がリスクの本質だ。大きなリリースには 2 つの問題がある。
- 検出の遅延: 変更範囲が広いほど、問題の原因特定に時間がかかる
- ロールバックのコスト: 多数の変更を含むロールバックは、別の問題を引き起こすリスクがある
小さく変えることで、失敗を早く検知し、影響範囲を局所化できる。
【大きなリリース】
変更 A + B + C + D を一度にリリース
→ 問題発生時「A か B か C か D のどれが原因?」
→ ロールバックで A〜D 全部を戻す必要がある
【段階的リリース】
変更 A → 問題なければ B → 問題なければ C → D
→ 問題発生時「直前の変更が原因」と即特定
→ A だけロールバック、影響は最小
4つの段階的変更パターン
1. Feature Toggles(機能フラグ)
コードをデプロイしつつ、フラグで機能の有効/無効を切り替える。
// 機能フラグの実装例
// フラグの状態はDBや設定サービス(LaunchDarkly等)から取得する
class FeatureFlags {
constructor(private readonly config: Record<string, boolean>) {}
isEnabled(flag: string): boolean {
return this.config[flag] ?? false;
}
}
// 使用側:フラグで新旧ロジックを切り替える
class OrderService {
async calculateDiscount(order: Order): Promise<number> {
if (this.flags.isEnabled('new-discount-algorithm')) {
return this.newAlgorithm.calculate(order); // 新機能
}
return this.legacyAlgorithm.calculate(order); // 旧機能(フォールバック)
}
}
注意: Feature Toggle は一時的なものとして扱う。長期間残り続けたトグルは「技術的負債」になる。使い終わったらコードから削除する。
2. Blue-Green Deployment
本番環境を Blue(現行)と Green(新バージョン)の 2 環境で運用し、ロードバランサーで切り替える。
┌─────────────┐
ユーザー ──→ │ ロードバランサー│
└──────┬──────┘
│
┌──────────┼──────────┐
↓ ↓
┌───────────┐ ┌───────────┐
│ Blue 環境 │ │ Green 環境 │
│(現行 v1) │ │(新版 v2) │ ← まずこちらに新バージョンをデプロイ
└───────────┘ └───────────┘
(すぐロールバック可能) (テスト完了後に切替)
- メリット: ロールバックがロードバランサーの切り替えだけで完了
- デメリット: インフラコストが約 2 倍、DB スキーマ変更との組み合わせが複雑
3. Canary Release
新バージョンへのトラフィックを段階的に増やし、問題がなければ 100% へ移行する。
Phase 1: 新バージョンへ 1% のトラフィックを流す → モニタリング
Phase 2: 問題なければ 10% へ拡大 → モニタリング
Phase 3: 50% → 100% と段階的に移行
Fitness Function との接続: 各フェーズでエラーレート・レイテンシを自動チェックし、閾値を超えたらロールバックを自動化する。
4. Dark Launch(シャドウデプロイ)
本番トラフィックを新旧両方のバックエンドへ送信し、結果を比較する。ユーザーには旧バージョンのレスポンスだけを返す。
ユーザーのリクエスト
├─→ 旧バックエンド(レスポンスをユーザーへ返す)
└─→ 新バックエンド(結果を記録するが返さない) ← "Dark"
用途: 新バージョンの性能・挙動を本番トラフィックで検証したいが、ユーザーへの影響をゼロにしたい場合。アルゴリズム変更やパフォーマンス改善の検証に有効。
4パターンの比較
| パターン | ロールバック速度 | コスト | 適用場面 |
|---|---|---|---|
| Feature Toggle | 即時(フラグ切替) | 低 | 機能の段階的公開・A/B テスト |
| Blue-Green | 即時(LB 切替) | 中〜高(環境 2 倍) | リスクの高いインフラ変更 |
| Canary Release | 分〜時間(段階縮小) | 低 | 新バージョンの段階的移行 |
| Dark Launch | ─(ユーザー影響なし) | 低〜中 | アルゴリズム変更の事前検証 |
Fitness Function との接続
段階的変更を安全に進めるには、各フェーズで特性を自動検証する Fitness Function が必要だ。
Canary 5% → Fitness Function チェック(エラーレート < 0.1%、P99 < 200ms)
↓ OK なら
Canary 20% → Fitness Function チェック
↓ OK なら
Canary 100%(移行完了)
↓ NG なら
自動ロールバック(Feature Toggle を False に戻す)
「新旧コードが共存できるか」も Fitness Function で自動検証することで、人間の判断を挟まずに安全な段階的移行を実現できる。
関連概念
- → 進化的アーキテクチャ概要
- → 適応度関数の詳細
- → Expand-Contract パターン(DB 変更の段階的移行)
出典・参考文献
- Neal Ford et al., Building Evolutionary Architectures, Chapter 3 “Engineering Incremental Change”
- Jez Humble, David Farley, Continuous Delivery (2010) — デプロイパターンの詳細
- 1. 🧬進化的アーキテクチャとは:定義・誕生背景・3原則
- 2. 📐適応度関数(Fitness Functions):アーキテクチャ特性を自動検証する
- 3. 🔗適切な結合(Appropriate Coupling):Connascence と分散モノリスの罠
- 4. 🚀段階的変更(Incremental Change):Feature Toggle・Blue-Green・Canary・Dark Launch
- 5. 🔄Expand-Contract パターン:ゼロダウンタイムでスキーマ変更する
- 6. ✍️Dual Write:マイクロサービス分割時のデータ整合性パターンと落とし穴
- 7. 📤Outbox Pattern:トランザクション境界を越えた安全なイベント発行
- 8. 📡CDC(Change Data Capture):アプリを汚さずに変更を伝播する
- 9. 🐚Unix 哲学を現代アーキテクチャへ翻訳する
- 10. 🧅クリーンアーキテクチャが進化耐性をもたらす理由
- 11. 🏢Conway's Law:組織構造がアーキテクチャを決める
出典: 進化的アーキテクチャ(O'Reilly / Neal Ford, Rebecca Parsons, Patrick Kua)