Skip to main content

データベース Blue-Green デプロイ: 実践ガイド

Adela · 2026年2月28日

Blue-Green デプロイは、本番と同等の環境 (blue と green) を 2 つ用意し、一度に一方だけにトラフィックをルーティングします。新バージョンをデプロイするときは、待機側 (アイドル側) の環境に投入し、ロードバランサーを切り替えます。ロールバックは切り替えを戻すだけです。

このモデルはステートレスなアプリケーションサーバーには綺麗に当てはまります。データベースはステートフルです。両環境が同じデータを共有するか、最終的に同じデータに収束する必要があります。green に当てたスキーママイグレーションは、同じテーブルを読む blue 側アプリを壊します。本ガイドでは、データベース Blue-Green デプロイ特有の難しさと、それぞれの扱い方を整理します。

Blue-Green デプロイとは

Blue-Green デプロイは、本番同等の環境を 2 つ維持するリリース戦略です。任意の瞬間に、一方の環境 (たとえば blue) が実トラフィックを処理します。もう一方 (green) はアイドルで、次リリースのステージングに使われます。

Blue-Green デプロイのアーキテクチャ: ロードバランサーがアクティブな blue へトラフィックをルーティング、green は新リリースを受けるBlue-Green デプロイのアーキテクチャ: ロードバランサーがアクティブな blue へトラフィックをルーティング、green は新リリースを受ける

リリースの流れ:

  1. 新バージョンをアイドル環境 (green) にデプロイ。
  2. blue が実トラフィックを処理している間、green に対してスモークテストを走らせる。
  3. ロードバランサーを blue から green に切り替える。
  4. green を監視する。問題があれば blue に戻す。
  5. green が安定したら、次回のリリース用に blue が新たなアイドル環境になる。

主な利点は、ほぼ瞬時で低リスクな切り替えです。ロールバック経路 (ロードバランサーを戻すだけ) は昇格と同じ操作なので、悪いデプロイの影響範囲が限定されます。

データベース Blue-Green デプロイ特有の難しさ

アプリケーションサーバーはステートレスです。v1 と v2 を並走させ、どちらかにトラフィックを流し、もう一方を破棄しても、調整は要りません。データベースはそうではありません。

両環境が同じデータを指す。 別々のデータベースを 2 つ用意 (高コスト、同期も複雑) しない限り、blue と green は同じテーブルを読み書きします。ordersNOT NULL カラムを足すスキーマ変更は、その瞬間からそのカラム無しで挿入しようとする blue アプリを壊します。

スキーマ変更は切り替えで戻せない。 green に blue が知らないカラムがあると、blue の書き込みは失敗します。green が使っていたカラムを削除すれば、green が壊れます。ロードバランサーの切り替えは可逆ですが、スキーマ移行はたいてい不可逆です。

両バージョンが同時に動く窓がある。 カットオーバー中、blue の進行中リクエストはまだ処理されています。旧コードと新コードの綺麗な切れ目は保証できません。旧コードと互換でないスキーマ変更は、この窓でエラーを生みます。

カットオーバー後に書かれたデータは戻せない。 green に切り替え、green が新フォーマットでデータを書き、その後 blue に戻すと、blue はそのデータを理解できないかもしれません。データセットが壊れます。

これらはインフラ層では解けません。スキーマ変更に対する規律あるアプローチが必要です。

スキーマを後方互換に保つ: Expand/Contract パターン

Expand/Contract パターン (Parallel Change とも呼ばれる) は、Blue-Green やローリングデプロイで安全にスキーマ移行を行う標準的な方法です。原則は、スキーマ変更を複数フェーズに分け、各フェーズが旧コードと新コードの両方と互換になるようにします。

フェーズ 1: Expand

何も削らずに新しい構造を追加する。データベースは両バージョンのアプリをサポートする状態になります。

例: カラム user_nameusername にリネームする

-- フェーズ 1: 新カラムを追加。旧 (user_name) と新 (username) の両方が存在する。
ALTER TABLE users ADD COLUMN username VARCHAR(255);

-- 旧データから新カラムへバックフィル
UPDATE users SET username = user_name WHERE username IS NULL;

この時点で: 旧アプリは user_name を読み書きし、新アプリは username を読み書きする。どちらも動く。

フェーズ 2: 新アプリケーションコードをデプロイ

username を使う新バージョンをアイドル環境にデプロイし、トラフィックを切り替えます。Expand フェーズのスキーマと新コードが本番で動いている状態です。

監視する。問題があれば戻す。旧カラムはまだ残っており、旧コードもまだ動く。

フェーズ 3: Contract

新コードが許容できる監視期間 (リスク許容度に応じて数時間〜数日) 安定して動いた後、旧構造を削除します。

-- フェーズ 3: 走っているコードがどれも参照していないので、旧カラムを削除
ALTER TABLE users DROP COLUMN user_name;

このクリーンアップはデプロイ済みコードが誰も user_name を参照していないため安全です。

Expand/Contract のルール

このパターンが機能するのは、すべてのスキーマ変更が次のルールに従うときだけです。

変更直接デプロイしてよいか?Expand/Contract が必要か?
NULL 許容カラムの追加YesNo
デフォルト値付き NOT NULL カラムの追加Yes (慎重に)大きなテーブルでは推奨
カラムリネームNoYes
カラム削除NoYes (Contract フェーズのみ)
索引追加 (CONCURRENTLY)YesNo
カラムの型変更NoYes
外部キー制約の追加要注意旧コードが違反し得るなら Yes

判定の要点: 現行版と新版のアプリケーションコードが、このスキーマに対して同時に正しく動けるか?

ステップごとの実例: Bytebase を使ったデータベース Blue-Green デプロイ

Bytebase はマルチ環境のデプロイパイプラインを通じて Blue-Green パターンと直接対応します。各環境 (Dev、Staging、Production-Blue、Production-Green) は Bytebase の独立したターゲットで、それぞれの承認・デプロイ規則を持ちます。

環境のセットアップ

Bytebase で順に 4 環境を作ります: DevStagingProduction-BlueProduction-Green。各環境はデータベースインスタンスにマップされます。

マイグレーションの提出

開発者は Bytebase 経由でスキーマ変更を提出します。変更はパイプラインを進みます — まず Dev、次に Staging、そして本番環境へ順に。

Bytebase の Issue 詳細: SQL diff、環境ごとのデプロイステージ、DBA 承認制御を含むスキーママイグレーションBytebase の Issue 詳細: SQL diff、環境ごとのデプロイステージ、DBA 承認制御を含むスキーママイグレーション

どの環境に到達する前にも、Bytebase の SQL レビュールールが自動で走ります。次のような点を確認します。

  • UPDATE/DELETEWHERE 句欠落
  • デフォルト無しの NOT NULL カラム追加
  • テーブルをロックする文
  • 命名規約違反

違反があれば Issue は解消まで進めません。

アイドル環境へデプロイ

変更が本番ステージに来たら、まずアイドル環境 (たとえば Production-Green) にデプロイします。Production-Blue は引き続き稼働し、トラフィックを受けています。

Bytebase は適用された正確な SQL、タイムスタンプ、承認者を記録します。変更は実トラフィックに触れる前に変更履歴で確認できます。

切り替えと監視

Production-Green にデプロイして検証したらロードバランサーを切り替えます。Production-Green が本番、Production-Blue がアイドルです。

新リリースに問題があれば戻します。スキーマは Expand フェーズなので、旧コードも新コードもまだ動きます。

Contract フェーズを実行

新コードが監視期間中安定して動いたら、Bytebase を通じて Contract マイグレーションを提出します。旧アプリケーションコードが使っていた旧カラムや制約を削除します。同じパイプライン、同じレビュープロセスを通します。

Bytebase のデータベース変更管理ワークフローでは、Contract フェーズを含むすべてのマイグレーションに承認の証跡が残ります。何週間後に問題が起きても、何が、いつ、誰の承認で変わったかを正確に追えます。

Blue-Green vs Canary vs Rolling: スキーマ変更の観点

3 戦略はスキーマ互換性の含意が異なります。

戦略トラフィックパターンスキーマ互換性の要件
Blue-Green一括切り替え切り替え時間帯 (数分〜数時間) の間、両バージョンを同時に支える必要
Canary少量から段階的に新バージョンへカナリア期間全体 (数時間〜数日) の間、両バージョンを支える必要
Rollingインスタンスを 1 つずつ更新、旧新コードが同居ロールアウト期間全体 (インスタンスごとに数分〜数時間) の間、両バージョンを支える必要

Blue-Green は重なりの窓が最短で、推論しやすいモデルです。Canary は最長で、旧新コードが数日同居します — Canary でのスキーマ変更は、観測期間全体にわたって後方互換でなければなりません。

3 戦略とも Expand/Contract の恩恵を受けます。Blue-Green は Contract フェーズが最もシンプルです — blue のコードが走っていない明確な時点が存在するからです。

ハマりがちな落とし穴と回避策

Expand フェーズを飛ばしてスキーマ変更を直接デプロイする

最もよくある間違いは、データベース移行をアプリケーションデプロイのように扱うことです: 新スキーマを green に投入してトラフィックを切り替え、終わり。旧コードが必要としているものをスキーマから外していたら、切り替え窓で blue のリクエストが落ちます。必ず先に Expand しましょう。

長時間マイグレーションがロックを保持する

大きなテーブルへの ALTER TABLE は数分にわたって排他ロックを保持し、すべての読み書きをブロックし得ます。PostgreSQL では、ADD COLUMN のデフォルト設定を ALTER インラインではなく分離して指定し、索引は CREATE INDEX CONCURRENTLY で構築しましょう。本番サイズのデータでステージングのマイグレーション所要時間を測ってから昇格します。

Contract フェーズを忘れる

Expand はカラムを足し、旧カラムを残します。Contract フェーズが無いと、データベースは死んだカラム、古いテーブル、孤児になった索引を抱え込みます。Contract マイグレーションは任意のクリーンアップではなく、必須の後続作業として扱いましょう。Bytebase の Issue やチケットシステムに明示的に記録し、こぼれ落ちないようにします。

ロールバックをテストしない

Blue-Green の価値はロールバック経路です。実際に戻したことが無いなら、動くかは分かりません。デプロイのランブックにロールバックテストを含めましょう。green に切り替えてスモークテスト、blue に戻してまたスモークテスト。インシデント前に経路を検証しておきます。

環境間のスキーマドリフト

Dev、Staging、Production-Blue が互いにドリフトしていると、Dev で通ったマイグレーションが本番で失敗します。データベーススキーマドリフトはデプロイパイプラインの静かな殺し屋です。Bytebase のドリフト検知は、各環境を期待スキーマ状態と照合し、マイグレーション実行前に差分をフラグします。

デプロイインフラを過剰設計する

データベース層の Blue-Green に物理データベースクラスタを 2 つ用意する必要はありません。多くのチームはデプロイパイプライン内で 2 つの論理的な環境スロットとして実装し、同じ DB インスタンスへスキーマ変更を慎重に管理しながらルーティングします。物理クラスタの二重化は、環境間でデータの隔離が必要なときだけ — それは稀です。


Blue-Green デプロイは、アプリケーション層のリリースリスクをロードバランサーの切り替えに帰着させます。データベース層はもっと作業が必要です: Expand/Contract のマイグレーション、後方互換なスキーマ変更、規律ある Contract フェーズ。ツール (マイグレーション管理の Bytebase、トラフィックルーティングのロードバランサー設定) は仕組みを担います。規律はスキーマ設計の側にあります。

Bytebase でのマルチ環境デプロイワークフローの詳細はデータベースのマルチ環境デプロイを参照。スキーマ変更をこのパイプラインに流し込む CI/CD 統合はデータベーススキーママイグレーションのための CI/CD パイプライン構築を参照してください。

ブログに戻る

データベース開発のスタンダードを体験する