ロールバックとは、ソフトウェアや設定の変更を差し戻し、以前の正常な状態に復元するリカバリ操作のことです。Kubernetesでは、デプロイ履歴によって デフォルトで10個の古いReplicaSetが保持されますが、PostgreSQLでは ROLLBACK 以前にコミットされたデータではなく、現在のトランザクションによる更新が破棄されます。
リリースが公開され、最初のユーザーがアプリを開いた直後、プロダクトチームが祝っている間もなくサポートチケットが届き始めます。決済画面がクラッシュしたり、新しい API レスポンスが古いクライアントを壊したり、設定変更によってリクエストが誤ったパスへ送られたりします。チームは、どのファイルが変わったか推測したり、全ユーザーに再インストールを依頼したりすることなく、サービスを復旧させる必要があります。
そこでロールバックの出番です。ロールバックは「予防」ではなく、魔法の「元に戻す」ボタンでもありません。新しいリリースはすでに適用されています。ロールバックとは、そのリリースがエラー、パフォーマンス低下、クラッシュ、または予期せぬ挙動を引き起こした際の、制御されたレスポンスです。実際には、通常は以前のアプリケーションバージョンを再デプロイするか、バージョン管理された設定を復元し、サービスが許容可能な状態に戻ったことを検証します。 障害解析の手法 ロールバックはインシデントを収束させますが、原因を解明するわけではないため、その後にチームが行う解析手法が重要になります。
目次
- デプロイ失敗の現実
- モダンなシステムにおけるリリース履歴の保持方法
- データベースとデータのロールバックに潜む危険性
- 切り戻しを判断する運用上の意思決定
- モバイル/クロスプラットフォームアプリの即時リカバリ
- レジリエントなリリース戦略の構築
- より安全なデプロイのための要点
デプロイ失敗の現実
あるモバイルチームが、ナビゲーションの変更とバックエンド互換性の更新を含む新しいbundleをリリースしました。まず段階配信の対象ユーザーに届きます。数分以内に、主要画面が読み込めないという報告がユーザーから寄せられました。モニタリングではエラーが増加していますが、チームは問題の原因がbundleにあるのか、APIにあるのか、フィーチャーフラグなのか、依存関係なのかをまだ特定できていません。
影響を受けるユーザーが増え続ける中で、完璧な診断を議論するのは安全な対応ではありません。もしチームに動作確認済みのアーティファクトがあれば、ロールアウトを停止してそのバージョンを復元できます。エンジニアが欠陥を調査し修正を準備している間に、アプリケーションは以前に検証済みの状態へと戻ります。
ロールバックは「予防」ではなく「復旧」である
予防 不具合のある変更がユーザーに届く前に阻止する試みです。テスト、codeによるレビュー、依存関係のチェック、カナリアリリース、承認ゲートなどがこれに当たります。 ロールバックは、予防策が失敗した際、または本番環境で予期せぬ挙動が発生した後に開始されます。
ロールバックはデリバリーシステムの複数の部分を対象にできます:
- アプリケーション code: 以前の実行ファイルまたはWeb bundleを再デプロイする。
- 設定: バージョン管理された設定、ルーティングルール、または機能構成を復元する。
- アセット: 互換性のある画像、スクリプト、またはコンテンツファイルに戻す。
- 機能の公開範囲: キルスイッチやオーディエンス制御で新しい機能を無効化します。
- データ: 実行中のトランザクションの中止やバックアップからのデータ復元は、はるかに厳しい制約の対象になります。
最後のカテゴリは別途扱う必要があります。アーティファクトが不変で依存関係の互換性が保たれていれば、アプリケーションの code を戻すのは多くの場合簡単です。しかし、コミット済みのデータを戻すと、消失、破損、規制上の問題を引き起こす可能性があります。したがって、リリースのロールバックは、関連するデータベース操作がすべて安全に巻き戻せることを意味するわけではありません。
頻繁なデリバリーに迅速なリカバリが必要な理由
現代の継続的デリバリーではリリース頻度が高まります。そこで実用的な要件が生まれます。失敗した変更の運用コストは限られた範囲に収めなければなりません。素早くデプロイできても、復旧に長い手動プロセスが必要なチームは、デリバリーの半分しか最適化できていません。
手動での切り戻しも可能ですが、どのファイルが変更され、どのサーバーが更新され、どの設定が前のリリースのものだったかをオペレーターが覚えておく必要があります。このプロセスはインシデント時にもろさを露呈します。自動化されたシステムは、不変のアーティファクトを保持し、ヘルスシグナルを監視し、定義済みの条件を満たしたらロールバックすることで、その道筋を改善します。
実践ルール: ロールバックは、障害時に誰かがなんとかする緊急ボタンではなく、リハーサル済みの本番機能として扱いましょう。
ロールバックは恒久的な解決策でもありません。一時的にサービスを復旧させるだけで、根本的な欠陥は残ったままです。エンジニアは引き続き、トリガーの特定、失敗したリリース中に書き込まれたデータの評価、そして修正版のリリースや、さらなる運用上の意思決定を行う必要があります。
モダンなシステムがいかにしてリリースの履歴を保持するか
リカバリシステムは、特定・取得できるものしか復元できません。依存関係がドリフトした状態でビルドされていたり、バイナリが上書きされていたり、あるいはネイティブシェルがそのbundleをサポートしなくなっていたりする場合、古いソースコミットを保持しているだけでは不十分です。
モダンなリリースシステムは、ソースからデプロイされたアーティファクトまでの証跡(chain of evidence)を保持することで、この問題を解決します。チームは安定したリビジョンにタグを付け、依存関係グラフをロックし、アドレス指定可能なアーティファクトをビルドして、どのアーティファクトが各環境に到達したかを記録します。この記録があることで、運用担当者は「前のバージョンに戻す」といった曖昧な指示ではなく、具体的なターゲットを指定できるようになります。

具体的なモデルとしてのKubernetes
Kubernetesはその構造を明確に示しています。DeploymentがReplicaSetを制御し、そのReplicaSetがデプロイのリビジョンを保持します。Kubernetesはデフォルトで 10個の古いReplicaSetを保持し、チームは spec.revisionHistoryLimitを使用してその保持数を変更できます。値を 0に設定するとロールバック機能が完全に無効化されます。詳細は Kubernetes Deployment のリファレンス.
オペレーターは、直前のリビジョンに戻るか、特定の履歴リビジョンを選択できます。ロールバックによって、コンテナイメージやラベルなどのフィールドを含む Deployment の Pod テンプレート設定が変更されます。ただし、レプリカ数などの無関係なフィールドは自動的には元に戻りません。その後、rollout-status を確認することで、ターゲットのリビジョンが正常に動作しているかを検証できます。
この違いは、モバイルや Web bundle の配信において重要です。システムは以下の項目を記録すべきです:
- アクティブなバージョン: 各環境、channel、またはデバイスがどのリリースを受け取ったか。
- アーティファクトの識別情報: 上書き可能なファイルではなく、コンテンツアドレス可能、または不変(immutable)なビルドであること。
- 依存関係の互換性: 以前の bundle が、現在の Native Build、API、サービス、およびデータスキーマと動作するかどうか。
- リカバリの結果: デバイスやインスタンスが、復元されたリリースを正常に適用できたかどうか。
「Previous(以前)」とは、特定のアーティファクトを指すものでなければなりません。
例えば、次のようなラベルは previous 不変(immutable)なリリースに紐付いている場合にのみ有効です。もしチームがそのラベルの背後にあるファイルを上書きしてしまうと、誰にも気づかれずにリカバリ対象が変わってしまう可能性があります。また、アーティファクトがストレージから期限切れで削除されている場合、デプロイシステムがリビジョン番号を把握していても、復元に必要なバイナリデータが不足していることがあります。
Capacitor アプリケーションでは、Web bundle もネイティブシェル内で動作します。以前の JavaScript bundle が、現在のシェルで変更されたネイティブプラグイン、権限、またはブリッジの挙動に依存している場合があります。互換性を確認せずに復元すると、ある障害を別の障害に置き換えてしまうことになりかねません。
この バージョン管理とロールバックへの Capgo なアプローチ これはより広範な原則を反映しています。つまり、リリース履歴は明示的かつ取得可能であり、各ビルドを受け取った対象と紐付いていなければなりません。ロールバックが成功するかどうかは、チームが次の3つの問いに即座に答えられるかにかかっています。「何が稼働していたか」「何が安定していたか」「現在の周辺システムと組み合わせて安全に実行できるものは何か」
データベースとデータ・リバーサルに潜む危険性
デプロイの失敗により、チームに「とにかく前のバージョンに戻して」という緊急の指示が飛ぶことがあります。実行可能な code であれば、それは機能するかもしれません。しかし、データベースにおいては危険です。コミットされた顧客のアクティビティを、クリーンに巻き戻すことは不可能な場合があるからです。
アプリケーションのロールバックとデータのロールバックは、失敗のパターンが異なる別個の操作です。 code のリリースは、多くの場合、別の不変なアーティファクトで置き換えることができます。しかし、スキーマのマイグレーションによってフィールド名が変更・削除されたり、保存された値が変換されたり、後続の書き込みで使用される前提条件が変更されたりすることがあります。注文、決済、メッセージ、レコード、同意情報は、すべて有効なユーザーデータです。アプリケーションのリリースに失敗したからといって、これらが消失してはなりません。
code とスキーマの同期が崩れる理由
リリースAが古いスキーマを想定している一方で、リリースBがカラムを追加したり、値の保存方法を変更したりする場合を考えてみましょう。Bをデプロイしてマイグレーションを実行した後、Aにロールバックすると、古い code が既に存在しないフィールドをクエリしたり、新しいデータを誤って解釈したりする可能性があります。
逆のパターンでは、また別の失敗が発生します。リリースBのプロセスがアクティブな状態でデータベースをリバートすると、書き込みが失敗したり、不完全な状態が残ったりすることがあります。code とデータベースの両方をリバートすれば綺麗に解決するように見えますが、デプロイ後に発生した正当なアクティビティまで消去してしまう可能性があります。 アプリケーションのロールバックとデータのロールバックの違い これはデータベース操作だけでなく、あらゆるリリース計画において考慮すべき事項です。
PostgreSQLの例で、トランザクションのロールバックが何を行うかを見てみましょう。 ROLLBACK 現在のトランザクションを中断し、そのトランザクション内で行われた更新を破棄します。これにより、一部のみ適用された書き込みが永続化されるのを防ぎます。ただし、以前のトランザクションでコミットされた変更を元に戻すことはできません。 ROLLBACK トランザクションブロックの外で実行しても、保存されたデータは元に戻りません。
前進するためのマイグレーション設計
より安全なリリース設計では、移行期間中もアプリのバージョンとスキーマ変更の互換性を維持します。また、チームは以下の項目を文書化すべきです: Capacitor アプリ向けの SQLiteの暗号化手法、スキーマの互換性、アクセス制御、およびリカバリ手順。
「Expand-and-contract(拡張と縮小)」方式のマイグレーションは、通常以下の手順で行われます:
- Expand(拡張): 既存の機能を削除せずに、新しいスキーマ機能を追加します。
- Adopt(採用): 両方の形式を読み書きできる code をデプロイするか、旧パスを保持したまま新しいパスを導入します。
- Migrate(移行): モニタリングと整合性確認を行いながら、制御されたプロセスで既存のレコードを移行します。
- Contract(縮小): 依存するバージョンが不要になったことを確認した後に、古い構造を削除します。
古いアプリケーションが自身のコントラクトをサポートするスキーマを引き続き利用できるため、この一連の流れによって code のロールバックの実現可能性が高まります。ただし、すべてのロールバックが安全になるわけではありません。リカバリによって新たな不整合が発生するリスクを低減できる、という点に注目してください。
Fintech、ヘルスケア、eコマースなどのシステムでは、監査可能性、プライバシー制御、決済状態のハンドリング、および照合計画も必要になります。有効なトランザクションを差し戻したり、その後のユーザーアクティビティを消失させるスナップショットを復元したりするよりも、フォワードフィックス(修正パッチの適用)の方が安全な場合があります。
データベースの原則: code のロールバックは、依存関係とデータコントラクトがその操作をサポートしている場合にのみ自由に行ってください。別途テスト済みの復元手順によって証明されない限り、コミットされたデータは「前進し続ける記録」として扱うべきです。
デプロイ前に、各リリースコンポーネントを可逆性に基づいて分類してください。Code、設定、機能の公開状況、アセット、スキーマ、ユーザーデータは、それぞれ異なるリカバリルールに従います。テスト済みのバックアップは致命的な破損時には役立ちますが、バックアップの復元は後方互換性のあるマイグレーション設計の代わりにはなりません。
切り戻しを判断する運用上の意思決定
ロールバックは単なるデプロイコマンドではなく、運用上の意思決定です。発生している問題がリリースに起因するものか、以前の状態に戻しても安全か、ロールバックを正当化できるほど十分な数のユーザーが影響を受けているか、あるいはフォワードフィックスの方が効果的にリスクを軽減できるか、といった判断を下す責任者が存在しなければなりません。
DORAでは、即時の介入(多くの場合ロールバックやホットフィックス)を必要とするデプロイを「変更失敗率(change-failure rate)」として扱い、デプロイ失敗からの復旧時間を別途追跡します。これにより、ロールバックは信頼性のイベントであると同時に、後述のデリバリーパフォーマンスの成果でもあります。 DORAメトリクスの歴史.
インシデント発生前にトリガーを定義する
優れたチームは、リリース設計の段階でロールバック条件に合意しています。トリガーには、クラッシュ信号、エラー率、ヘルスチェックの失敗、サポートへの報告、カナリア比較などを組み合わせられます。単発のノイズで必ずしもリリースを戻すべきではありませんが、監視対象のユーザー間で明確なパターンが見られたら、定義済みの対応を取るべきです。
自動ロールバックが適切なのは、失敗が十分に理解され、可逆的で、信頼できるシグナルで観測できる場合に限られます。あらゆる異常に反応する自動システムは、バージョン間を行き来したり、根本原因を隠したり、互換性のない依存関係を繰り返し持ち込んだりして、インシデントを悪化させる可能性があります。
モバイルアプリでは、判断に追加のコンテキストが必要です:
- オフラインユーザー: 一部のデバイスはすぐにアップデートを確認しません。
- バージョンの混在: 新旧のクライアントが長期間共存することがあります。
- 段階的公開: チャネルやカナリアが本番より先に問題を明らかにすることがあります。
- Nativeとの互換性: 復元されたWeb bundleは、インストール済みのshellで動作する必要があります。
- データへの影響: codeのロールバックでは、すでにバックエンドに書き込まれたデータを元に戻せない場合があります。
ロールバック vs ロールフォワード
ロールバックは以前の状態に戻すもので、ロールフォワードは修正プログラムを適用するものです。どちらが常に安全とは限りません。
ロールバックは通常、表示上の不具合、設定ミス、または永続的な状態を変更する前に失敗したリリースに適しています。一方、マイグレーションが既に実行済みであったり、ユーザーが有効なレコードを作成済みであったり、旧バージョンのアプリが現在のスキーマをサポートしていない場合は、ロールフォワードの方が安全な場合があります。また、不具合のある機能が特定できているなら、リリース全体を入れ替えるよりもキルスイッチの方がより安全です。
ランブックには、インシデントコマンダー、実行権限を持つ担当者、成功を確認するためのヘルスシグナル、およびプロダクトやサポートへの連絡経路を明記すべきです。また、いつロールバックを諦めて修正(fix forward)に切り替えるかも定めておく必要があります。
有用なランブックには以下を記録します:
- 対象のリビジョン およびそのアーティファクトの場所。
- 互換性チェック ネイティブクライアント、サービス、依存関係、およびスキーマに対して適用されます。
- 影響範囲(blast-radius)の制御(チャネル、コホート、カナリアなど)
- 成功基準(リカバリシグナルやユーザーへの影響を含む)
- フォローアップ担当者(修正版のリリースおよびインシデントレビューの責任者)
この ロールアウトの停止とロールバックの違い この違いを理解することは運用上非常に重要です。停止はさらなる影響を抑えるものですが、ロールバックは影響を受けたユーザーが受け取る内容を能動的に変更するものです。チームはどちらかを選択する前に、どちらのアクションが必要かを判断しておくべきです。
モバイル/クロスプラットフォームアプリの即時リカバリ
従来のモバイルリリースにおけるリカバリは、App Storeなどの配信に依存します。欠陥がネイティブバイナリにある場合、チームは修正済みまたは以前のバイナリを用意して各ストアに提出し、ユーザーに配信されるのを待つ必要があります。このプロセスはネイティブの変更には適していますが、欠陥がJavaScript、CSS、設定、テキスト、またはWebアセットに限定されている場合には、大きな摩擦を生みます。
OTA(Over-the-air)配信は、Webレイヤーの変更におけるリカバリパスを変化させます。live update システムを使用すれば、署名済みbundleを特定の対象に公開し、次回の起動時やアップデート確認時にデバイスへ適用させると同時に、以前のbundleをフォールバックとして保持できます。ただし、ネイティブな code やプラットフォーム権限が変更される場合には、引き続きストア審査が必要であり、データのロールバックを保証するものでもありません。

ストア配信とライブアップデートは解決する問題が異なる
| リカバリの必要性 | ストア経由のバイナリリリース | 署名済み live update |
|---|---|---|
| ネイティブプラグインまたは権限の変更 | 適切 | 代替手段ではない |
| JavaScriptまたはCSSの欠陥 | 低速なリカバリパス | ポリシーと互換性が許容する場合に最適 |
| 配信対象の制御 | チャンネル保存とロールアウト制御 | ターゲットチャンネルと段階的配信 |
| リカバリ対象 | 公開済みバイナリ | バージョン管理されたWeb bundle |
| 主要な依存関係 | ストア配信 | Updater、署名、互換性、およびオブザーバビリティ |
次のようなプラットフォーム: Capgo Capacitor live updatesをサポートし、署名済みWeb bundleをターゲットチャンネルに配信して、バージョン履歴を保持し、次回起動時またはアップデート確認時に更新を適用し、新しいbundleが設定済みのヘルスチェックに失敗した場合にロールバック保護を提供します。差分配信では変更されたファイルのみを送信でき、チャンネルを使ってbeta、staging、production、顧客別のオーディエンスを分けられます。これらの機能により、チームはWebレイヤーのリリース失敗時の影響範囲を抑えられますが、ネイティブシェルとの互換性やバックエンドのデータコントラクトを検証する必要性を回避できるわけではありません。
自動フォールバックには信頼できるヘルスシグナルが必要
アップデーターは、単にダウンロードが完了しただけでbundleを「正常」と判断すべきではありません。取得、インストール、起動、そして実際のアプリケーションの動作状況を区別して評価する必要があります。新しいbundleがクラッシュしたり、次回の起動時にヘルスチェックに失敗したりした場合、App Storeのバイナリ全体を再ダウンロードすることなく、デバイスを直前の安定したバージョンに戻すことができます。
ただし、このリカバリにも限界はあります。デバイスがオフラインであったり、失敗したアップデートによって既にサーバー側のデータが変更されていたり、あるいは以前のbundleがインストール済みのネイティブシェルと互換性がなかったりする場合です。デバイスごとのログやバージョン採用データがあれば、サポートチームはどのユーザーがどのbundleを受け取り、フォールバックが機能したかどうかを判断できます。
この Capacitor アップデートのロールバック設定ガイド リリースポリシーと併用すべきであり、置き換えるものではありません。すべてのアーティファクトに署名し、プロダクションチャネルへ公開できる人を制限し、フォールバック用のバージョンを保持し、実機で失敗経路をテストしてください。高速配信は、復元されたbundleが意図したものであるとシステムが証明できて初めて価値を持ちます。
レジリエントなリリース戦略の構築
ロールバックへの備えは、リリースシステム全体の特性です。オブジェクトストレージに古いビルドが残っていても、チームがその依存関係を特定できず、どのデバイスがそれを採用したか把握できず、本番環境に近いデータでリカバリをテストしたことがなければ、意味のある保護にはなりません。

まずはアーティファクトの連鎖から始めましょう。安定したソース状態にタグを付け、依存関係をロックし、署名済みビルドを保持し、公開済みリリースは決して上書きしません。次に、各アーティファクトを環境、チャネル、デプロイイベントに紐付けます。チームは開発者のローカルマシンに頼らず、何が起きたかを再現できるようにすべきです。
リカバリリスクを軽減する4つのコントロール
- 不変のアーティファクト: すべての本番bundleを一意のIDで保存します。「previous」ポインタはリリースを選択できますが、リリース自体を変更してはいけません。
- 互換性のあるマイグレーション: expand-and-contract手法を使い、制御された移行期間中にアプリの旧バージョンと新バージョンを共存させます。
- ガード付きの自動化: 実際のリリース失敗と一時的なサービス障害を区別できるシグナルに限って、フォールバックを自動化します。
- 依存関係の検証: 対象リビジョンを有効化する前に、ネイティブシェル、プラグイン、API、サービス、スキーマを確認します。
オブザーバビリティがこのループを完結させます。デバイスごとのバージョン、起動結果、updateのステータス、失敗理由、適用状況をキャプチャします。これらの記録により、サポートは「ユーザーがまだ失敗したbundleを使っているのか」「すでにフォールバックを受け取ったのか」「updateを一度もダウンロードしていないのか」を判断できます。
チームは、実際のデータや混在するクライアントバージョンを用いて、リカバリパスのシミュレーションを行うべきです。空の開発用データベースに対して code を復元するだけのテストでは、実際のレコード、古いスキーマ、保留中の書き込み、未完了のマイグレーションなどが原因で発生する互換性の問題を見逃す可能性があります。リカバリテストでは、認可、署名、アーティファクトの取得、チャネルのターゲティング、およびコミュニケーションプランも検証する必要があります。
リカバリの成否は、古いビルドが存在するかどうかで決まるのではありません。チームがいかに正確に影響範囲を制御し、互換性のある状態を復元できるかによって決まります。
リリース計画には、依存関係の調整に関する明確な責任範囲を含めるべきです。より広範なフレームワークを必要とするチームは、 アジャイルにおける依存関係の管理において、 その計画的な規律を活用することで、デプロイ前にモバイル、バックエンド、データベース、およびプロダクトの変更を同期させることができます。
実践的な準備状況のレビューでは、以下の点を確認します:
- 各チャネルでアクティブな正確なアーティファクトを特定できるか?
- インストール済みの code を変更せずに、公開範囲を停止できるか?
- 署名済みの互換性のあるbundleを復元できるか?
- アプリケーションのロールバック後も、データベースの安全性が保たれていることを証明できるか?
- サービス全体の集計レベルではなく、バージョンごとの失敗を検知できるか?
- 切り戻しが有効なデータを損なう場合に、ロールフォワードを選択できるか?
いずれかの回答が不明確なら、リリースプロセスにリカバリの抜けがあります。ユーザーが待っている間に場当たり的に対応するより、次のインシデントが起きる前にその抜けを埋める方がコストは低く済みます。
より安全なデプロイのための要点
ロールバックは、適用済みのソフトウェアや設定の変更を巻き戻し、既知の正常な状態に復元します。ただし、欠陥を防いだり、根本原因を修復したり、コミット済みのデータベース変更を自動的に取り消したりするものではありません。
アプリケーションのアーティファクトは不変(immutable)かつアドレス指定可能な状態に保ちましょう。すべてのリリースで、アクティブなバージョン、依存関係、native-shellとの互換性、対象ユーザーを追跡してください。スキーママイグレーションとユーザーデータは別々のリカバリ対象として扱ってください。code のロールバックではデータベースが変更されたままになる可能性があり、データベースのロールバックでは有効なレコードを破壊する可能性があるためです。
段階的なデリバリー、信頼できるヘルスシグナル、明示的な承認、テスト済みのランブックを使いましょう。モバイルチームでは、署名済みのOTA bundleが互換性のあるWebレイヤーの変更に対して迅速なリカバリを提供できますが、ネイティブの変更には依然として適切なバイナリリリースのパスが必要です。リカバリは、古いビルドがあるかどうかではなく、影響範囲(blast radius)の縮小とサービスの復旧が確認できたかで測ってください。
Capgo は、Capacitor と Electron チームに、署名済みのLive Update bundle、ターゲット配信チャンネル、バージョン履歴、デバイスごとのオブザーバビリティ、互換性のあるWebレイヤーリリース向けのロールバック保護を提供します。現在のリカバリパスを確認し、次の点でどう役立つかを見てください。 Capgo 影響の拡大を止め、既知の正常なbundleを復元し、インシデント対応を制御下に保つために。