PHPにおけるロールバックを伴うデプロイ戦略は、以前のバージョンへ戻すためのボタンを用意することではありません。互換性のないデータ、重複した非同期ジョブ、または破棄済みのルールを実行する進行中のプロセスを残さずにコードを撤回できるようにする運用設計です。ロールバックは、インシデント発生時の即興の対応ではなく、公開前に準備された選択肢でなければなりません。
小規模なデプロイは影響範囲を縮小します。導入する変数が少なく、原因となった変更を特定しやすく、復旧時間も短縮されます。ただし、小さな変更であっても、決済、認証、権限、在庫、通信に影響する可能性があります。したがって、変更の規模は技術的な制御や公開を停止するための明示的な基準の代わりにはなりません。
ロールバックはインシデントが起きる前に設計する

コードの復帰が容易なのは、変更が共有状態を変更していない場合だけです。本番環境では、あるバージョンがデータを書き込み、キューにメッセージを送信し、スケジュールタスクを有効化し、外部サービスを呼び出している可能性があります。こうした影響を確認せずに以前のcommitへ戻すと、最初のエラーを隠し、より診断が難しい問題を生むおそれがあります。
デプロイを承認する前に、チームは次の4つの質問に答えられなければなりません。
- 公開するアーティファクト:識別可能で、一度だけビルドされ、復元に利用できるバージョン。
- 変更される状態:データベーススキーマ、キャッシュ、ファイル、検索インデックス、キュー、外部プロバイダー、設定。
- その状態を読み書きできるバージョン:新しいコード、以前のコード、または一時的な期間における両方。
- 対応を強制するシグナル:エラーの閾値、重要な経路の失敗、キュー遅延、レイテンシの劣化、または確認済みの機能的影響。
復帰の単位を定義しておく必要があります。対象はアプリケーション全体、サービス、キューコンシューマー、または設定で有効化される機能になり得ます。ソフトウェアをインストールするデプロイと、動作を利用可能にするリリースを混同すべきではありません。これらを分離することで、非アクティブなコードをデプロイし、技術的な条件を検証した後に公開できます。
復帰可能性に応じて変更を分類する
すべての変更を同じように扱うことはできません。状態変更を伴わない表示の調整や内部修正は、通常、以前のアーティファクトを復元すれば復帰できます。一方、破壊的なマイグレーション、API契約の変更、またはすでに外部的な影響を生んだ新しいビジネスルールには、追加の戦略が必要です。
通常は復帰可能な変更
- 入出力の契約を維持するロジック修正。
- 削除されたフィールドに依存しない限りのテンプレート変更。
- 既存リソースを変更しない新しいルートまたはendpoint。
- スキーマやセマンティクスを変更しない内部最適化。
一時的な互換性が必要な変更
- カラム、JSONフィールド、イベントのリネームまたは置換。
- キューメッセージまたはwebhookのフォーマット変更。
- 既存データに対する新たなバリデーション制約。
- 認証、権限、計算ルールの変更。
- 外部システムで課金、注文、通知、変更を作成する連携。
共有データでは、最も安全なパターンは通常、拡張、移行、縮小です。まず互換性のある構造を追加し、次にコードが旧形式と新形式を一時的にサポートし、必要なデータを移行または補完して、旧バージョンを完全に撤去した後にのみ不要なものを削除します。たとえば、nullableなカラムを追加し、移行期間中に両方のフィールドへ書き込むことは復旧可能です。一方、以前のバージョンが使用するカラムを直接リネームまたは削除することは復帰可能ではありません。
マイグレーションはコードとは独立した成果物として扱う必要があります。前方へのみ進むマイグレーションは適切な場合がありますが、その場合、計画にはアプリケーションのロールバックがスキーマの復帰を意味しないことを明記しなければなりません。変更後に生成されたデータを削除する可能性がある場合、または結果が実際の本番状態に依存する場合は、自動ダウンマイグレーションを避けてください。
アーティファクト、設定、前提条件を準備する
同一のアーティファクトを環境間で進める必要があります。各サーバーで依存関係をビルドしたりコードを直接変更したりすると、どのバージョンが実行されているか把握できず、既知のバージョンへの復元も難しくなります。PHPアプリケーションでは、アーティファクトにバージョン管理されたコードと解決済みの依存関係を含められます。機密情報および環境固有の設定は、パッケージに埋め込まず、外部の仕組みで注入する必要があります。
最低限、バージョン識別子、公開日時、関連する機能設定、決定の責任者を記録してください。これにより調査と特定バージョンへの復帰の両方が迅速になります。
デプロイ前に、次を自動化され可視化された形で検証してください。
- 変更に見合ったユニットテスト、統合テスト、契約テスト。
- 依存関係の解決、およびPHPバージョン、拡張機能、必要なサービスとの互換性。
- マイグレーションの状態、データ拡張計画、推定実行時間。
- 依存先の健全性:データベース、キャッシュ、ストレージ、内部API、重要なプロバイダー。
- worker、キュー、スケジュールタスクの能力と挙動。
- 以前のアーティファクトの可用性と、それを復元するためにテスト済みの手順。
確認はPHPプロセスが応答することだけに限定してはなりません。ヘルスチェック用の経路はPHP-FPMが稼働していることを確認できますが、それでも認可エラー、低速なクエリ、ブロックされたコンシューマーは検出できない場合があります。不可逆なアクションを実行せずに重要な操作を表す、小規模な合成テスト用ルートを定義してください。
責任者と明確な制限を設けて段階的に公開する
段階的な公開は障害の範囲を縮小しますが、トラフィックまたはインスタンスを実際に分離できる場合にのみ機能します。インスタンスの一部を更新したり、制御されたセグメントに対して機能を有効化したり、リクエストの一部を新バージョンへ振り向けたりできます。選択はアーキテクチャと共有状態の種類によって決まります。
公開ウィンドウ中の役割を明示的に割り当ててください。
- 1人が手順を実行し、記録する。
- 別の1人が関連するメトリクス、ログ、トレースを監視する。
- 責任者は曖昧な承認を待たずに停止または復帰する権限を持つ。
- 変更が機微な操作に触れる場合、ビジネスチームまたはサポートチームは予想される影響を把握している。
観測ウィンドウも設定してください。公開し、正常なHTTPレスポンスを確認して次の変更へ進むだけでは不十分です。一部の不具合は、キューの処理、キャッシュの期限切れ、スケジュールタスクの実行、またはユーザーによるより長いフローの完了時に現れます。
公開後に検証する:サービス、データ、ビジネス上の影響
公開後の検証では、技術的シグナルと機能的シグナルを組み合わせる必要があります。一般的なメトリクスは有用ですが、安定した平均レイテンシが少数ながら重要な操作の失敗を隠すことがあります。
- 重要な経路:認証、主要な読み書き、決済、注文作成、権限を伴うアクション。
- エラー:PHP例外、5xxレスポンス、予期しない4xxの増加、バリデーションエラー、依存先の障害。
- パフォーマンス:endpointごとのレイテンシ、workerの飽和、データベース接続、リソース消費。
- 非同期処理:キューのサイズと滞留時間、リトライ、失敗メッセージ、冪等性。
- ビジネス上の影響:未完了のトランザクション、重複、無効な状態変更、またはチームが照合できるコンバージョン低下。
判断基準は検証可能でなければなりません。定義した経路が機能し、エラーの持続的な増加がなく、キューが許容可能な遅延の範囲内にある場合は継続します。なお診断を要する異常が発生した場合は、拡大を停止します。以前のアーティファクトが現在の状態と互換性を持ち、復元によって影響が明確に軽減される場合は復帰します。復帰が互換性を壊す、外部的な影響を取り消せない、または分離して検証済みの修正を適用するより時間がかかる場合は、フォワードフィックスします。
撤去したバージョンが開始したキューとプロセスを管理する
workerは不完全なロールバックの一般的な原因です。新バージョンで作成されたメッセージや、古いロジックを実行し続ける長時間プロセスが残っている一方で、Webコードだけを撤去する可能性があります。計画では、トレーサビリティを失わずにコンシューマーをドレイン、一時停止、再起動、隔離する方法を示さなければなりません。
仮想的なフローを考えてみましょう。PHPアプリケーションが注文確認のためのメッセージを公開します。新バージョンはメッセージにフィールドを追加し、送信前に注文の状態を変更します。これを撤去する必要がある場合、以前のコンシューマーは追加フィールドを安全に無視できる必要があります。あるいは、メッセージにバージョンを持たせ、互換性のあるコンシューマーへルーティングできるようにする必要があります。さらに、確認では冪等キーを使用し、リトライによって外部アクションが2回発生しないようにしなければなりません。
{
"event": "order.confirmation_requested",
"schema_version": 2,
"idempotency_key": "一意の操作",
"order_id": "注文ID"
}
復帰前に、必要であれば新規ジョブの投入を一時停止し、転送中のメッセージを特定して、どのコンシューマーが処理できるかを確認してください。その後、失敗とリトライを制御された形で確認します。迅速な復旧のためにキューを削除してはなりません。必要な証跡を失ったり、ビジネス操作を途中で未完了にしたりする可能性があります。
計画を反復可能な実践に変える

成熟した戦略は個人の記憶に依存しません。サービスごとに、承認済みコマンド、ログの場所、監視ダッシュボード、責任者、停止条件、既知の復帰制限を含む簡潔なrunbookを維持してください。特にインフラ、キュー、マイグレーション、連携の変更後には、代表性のある環境で手順を演習してください。
各インシデントまたはロールバックの後、検出、互換性、自動化、判断のどれに失敗があったかを確認してください。目標はすべての復帰を避けることではありません。十分な情報に基づいて復帰とフォワードフィックスのどちらかを選択し、局所的なインシデントをデータ損失やより大きな中断へ変えないことです。



