ロールバックが危険すぎる場合:ロールフォワードでシステムを動かし続ける方法
金曜日の午後、アプリケーションの新バージョンをデプロイしました。モニタリングダッシュボードはすべて正常に見えます。あなたは帰宅します。土曜日の朝、スマートフォンでバグレポートを確認します。デプロイ後にサインアップしたユーザーがプロフィール設定を完了できないという報告です。データベースには、ユーザーの部分的なデータを保存する新しいテーブルが追加されています。ここで決断を迫られます。
以前のバージョンにロールバックすべきでしょうか?もしロールバックした場合、その新しいテーブルのデータはどうなりますか?すでにプロフィールを入力したユーザーは、その進捗を失います。データベーススキーマは変更されており、それを元に戻すということは、実際のユーザー情報が含まれているテーブルを削除することを意味します。金曜日には単純に見えたロールバックが、今やデータ損失インシデントの予感に変わります。
これこそ、多くのチームがロールバックが常に安全な選択肢ではないと気づく瞬間です。別の道があります。それがロールフォワードです。
ロールフォワードの本当の意味
ロールフォワードはロールバックの逆です。古いバージョンに戻す代わりに、問題を修正した新しいバージョンを作成し、それを本番環境にデプロイします。変更を元に戻すのではなく、修正を追加することで前進し続けます。
論理は単純です。現在のバージョンにバグがあるなら、それを修正するパッチを書いて出荷するだけです。データベースはそのままにします。新しいテーブルもそのまま。ユーザーデータもそのまま。プロフィール設定フローを壊したコードだけを修正します。
このアプローチは最初は直感に反するように感じられます。多くのエンジニアは、何かが壊れたら元に戻すと早い段階で学びます。しかし、特にデータベース変更を伴う現代のシステムでは、元に戻すことは修正して前進することよりも難しい場合がよくあります。
ロールバックよりロールフォワードが適している状況
ロールフォワードは、3つの一般的な状況で威力を発揮します。
本番環境に影響を与えたデータベース変更
これはチームがロールフォワードを選択する最も頻繁な理由です。デプロイにデータベースマイグレーションが含まれている場合、アプリケーションコードのロールバックは話の半分に過ぎません。データベースの変更も元に戻す必要があります。マイグレーションでカラムが追加された場合は削除し、新しいテーブルが作成された場合はドロップする必要があります。そのテーブルに実際のユーザーデータがすでにある場合、ドロップすることはそのデータを失うことを意味します。
ロールバックに対応するために、元に戻せるマイグレーションを書くチームもあります。しかし、元に戻せるマイグレーションがあっても、データの問題は残ります。ユーザーは情報を入力し、トランザクションは記録され、テーブル間の関係が確立されています。スキーマを元に戻しても、新しいスキーマの下で入力されたデータは元に戻りません。
この状況では、ロールフォワードとはデータベースをそのまま維持し、アプリケーションコードを修正して再デプロイすることを意味します。ユーザーはデータを保持し、スキーマは一貫性を保ちます。変更されるのはバグのあるコードだけです。
数時間または数日後に発見された問題
すべてのバグが即座に検出されるわけではありません。ユーザーがしばらくシステムとやり取りした後に表面化するものもあります。問題に気づいた時点で、新しいバージョンはすでに数千のトランザクションを処理し、数百のレコードを作成し、元に戻すのが難しい方法でシステムの状態を変更しています。
このシナリオでロールバックすると、そのすべてのアクティビティが失われます。注文を出したユーザー、プロフィールを更新したユーザー、フォームを送信したユーザーは、自分の作業が消えてしまうことに気づきます。サポートチケットが殺到し、信頼は損なわれます。
ロールフォワードアプローチでは、ユーザーがすでに作成したデータを妨害することなくバグを修正できます。修正はデプロイ以降に発生したすべての上に重ねられます。
ダウンタイムが許されない重要なシステム
一部のシステムは、ロールバックにかかる時間を許容できません。ロールバックは瞬時には完了しません。コードの復元、データベースの復元、すべての確認、そして他に何も壊れていないことを確認する必要があります。有料顧客にサービスを提供したり、リアルタイム運用を扱うシステムにとって、その不確実性の期間は広すぎます。
ロールフォワードはシステムを稼働し続けます。修正を準備し、可能な限り迅速にテストし、デプロイします。プロセス全体を通じてシステムは稼働したままです。ユーザーはバグを少し長く経験するかもしれませんが、ダウンタイムは経験しません。
ロールフォワードの実践方法
プロセスは通常のデプロイとほぼ同じです。現在の本番コードからブランチを作成し、修正を書き、パイプラインを実行します。違いは緊急性と、取るかもしれないショートカットにあります。
多くのチームはホットフィックス用の別のパイプラインを持っています。このパスは、時間のかかるパフォーマンステストやセキュリティスキャンなどの重要でないステージをスキップします。レビュープロセスはより迅速です。テストは特定の修正と、それが影響を与える可能性のある領域に焦点を当てます。目標は、明らかな問題をキャッチしながら、可能な限り迅速に修正を本番環境に届けることです。
ロールフォワードにおける主要な緊張関係は、スピードと徹底性の間です。バグが重大な場合は、いくつかのチェックをスキップするかもしれません。バグが軽微な場合は、より慎重になる余裕があります。普遍的なルールはありません。各チームは、問題の深刻度と新しい問題を導入するリスクに基づいて決定する必要があります。
ロールフォワードのリスク
ロールフォワードは無料のパスではありません。それ自体にリスクが伴います。
最大のリスクは、修正が新しいバグを導入することです。急いでいるときは、根本原因を完全に理解していないかもしれません。症状にパッチを当てても、根本的な問題を見逃します。修正が出荷され、今度は1つではなく2つの問題を抱えることになります。
別のリスクは、修正が既存のコードと悪い相互作用を起こすことです。バグのあるバージョンが、修正が依存する何らかの動作を変更している可能性があります。以前は正常に動作していたものを誤って壊してしまうかもしれません。
一部のチームはハイブリッドアプローチを採用しています。まずシステムを安定させるためにロールバックし、その後時間をかけて根本原因を理解し、適切な修正を準備します。これは、ロールバックが安全で、システムが以前の状態への短時間の復帰に耐えられる場合にうまく機能します。しかし、ロールバックがリスクを伴う場合、ロールフォワードがより良い選択です。
ロールバックとロールフォワードの選択
決定は単純な質問に帰着します。どちらのオプションが総合的なリスクが低いか?
以下のフローチャートは、上記の判断ロジックをまとめたものです。
重要なデータベース変更のないアプリケーションの場合、ロールバックは通常より速く、より安全です。コードを元に戻し、システムは以前の状態に戻り、問題を適切に修正する時間が取れます。
データベーススキーマを変更したデプロイや、新しいデータを蓄積するのに十分な時間稼働しているデプロイの場合、ロールフォワードがより賢明な選択であることがよくあります。データ変更を元に戻すコストは、修正を書いてデプロイするコストよりも高くなります。
修正デプロイ後
ロールフォワードは修正が本番環境に届いた時点で終了しません。修正が実際に機能し、他に何も壊れていないことを確認する必要があります。エラー率を監視し、影響を受けた機能を確認し、ログの異常なパターンをチェックします。
疲れていてインシデントを終わらせたいだけのとき、確認ステップはスキップしがちです。しかし、それをスキップすることは、小さなインシデントをより大きなものに変える方法です。修正が意図したとおりに動作したことを確認するために、5分間取ってください。
ロールフォワードの実践的チェックリスト
ロールバックではなくロールフォワードを選択する場合、以下を使用してください。
- ロールバックがデータ損失やスキーマの不整合を引き起こすことを確認する
- 正確なバグを特定し、最小限の修正を書く
- バグシナリオと周辺機能をカバーするテストを実行する
- 緊急性が要求する場合にのみ重要でないステージをスキップして、通常のパイプラインを通じてデプロイする
- デプロイ後30分間、エラー率、応答時間、影響を受けた機能を監視する
- 何が起こったのか、なぜロールバックではなくロールフォワードが選択されたのかを文書化する
まとめ
ロールフォワードは失敗の兆候ではありません。それは、一部の変更はきれいに元に戻せないという現実に対する実用的な対応です。データベースが変更され、ユーザーがデータを入力し、システムが前進した場合、問題を修正する最も安全な方法は、より良いバージョンで前進し続けることであることがよくあります。
問題は、ロールフォワードが必要になるかどうかではありません。問題は、あなたのチームがロールバックが間違った選択であることを認識し、それに基づいて行動する準備ができているかどうかです。