障害対応の話になると、フォールバック(失敗時の代替動作)ってかなり早い段階で話題に上がります。外部APIが落ちた、DBが重い、ネットワークが不安定、そんなときに「どうする?」を決めるためです。
ただ、ここで一つ落とし穴があります。フォールバックを「技術的にできること」だけで決めると、後から業務や運用、コンプライアンスの観点で詰みます。
たとえば「キャッシュを返せばOK」「失敗したら後払いにしよう」みたいな案は、システムとしては動き続けます。でも業務領域によっては、規約違反や法令上の問題、監査で突っ込まれるポイントになり得ます。つまりフォールバックは、コードの話に見えて、実はプロダクトの意思決定でもあります。
この記事では、フォールバック処理を「どう書くか」ではなく、どう設計するかに軸を置いて解説します。さらに、指摘のあった「ビジネス側との合意」や「復旧後の整合性修復(戻し方)」を、使えるレベルまで掘り下げてみます。
概要:フォールバック設計で最初に押さえるべき全体像

フォールバック設計を一言でいうとこうです。
失敗したときに、ユーザー体験と業務要件を壊さずに、サービスをどう動かし続けるかを決めること
ポイントは「動かし続ける」だけじゃありません。動かし続けた結果、業務が破綻したり、後で整合性が取れなくなったり、監査に耐えなくなったら意味がありません。
なので、設計の最初に次の三点を決めるのがおすすめです。
1つ目は 何を守るか(優先順位)
2つ目は 何なら妥協できるか(縮退の許容範囲)
3つ目は 誰と合意しておくべきか(ビジネス・法務・運用)
技術だけで完結しない、と最初に腹落ちしておくと、後の設計がスムーズになります。
詳細解説:フォールバックを「設計」として組み立てる
フォールバック方針はビジネス側と合意が必要になる理由
「キャッシュを返す」「後で処理する」「別経路で受け付ける」などは便利な手段です。でも、業務領域によってはリスクになります。
代表的に揉めやすい観点を挙げます(当たり前のことかもしれませんが、、)。
正確性が必須の情報をキャッシュで返してよいか
在庫、価格、ポイント残高、利用制限、認可情報などは、古い値が混ざると事故につながります。ユーザーの画面上の表示だけでなく、裏側の業務処理まで誤る可能性があります。
キャッシュは強い武器ですが、「古くても問題ない情報」と「古いとアウトな情報」を分けるのが前提です。ここは技術者だけで判断せず、業務側と合意しておくのが安全です。
後回し処理や代替フローが規約・法令・監査に触れないか
「後で支払い」「後で確定」「一旦受け付ける」は、場合によっては契約条件や規約、監査要件に絡みます。決済や本人確認、権限付与などは特に慎重さが必要です。
大事なのは、「技術的に可能」ではなく、やってよい設計なのかを確認することです。フォールバック方針は、仕様の一部として扱うのが正攻法です。
障害時の案内文やUIも合意対象になる
「いま使えません」「後で反映されます」「一時的に制限中です」などの文言は、ユーザーへの約束になります。文言ひとつでクレームや問い合わせが増減しますし、場合によっては法務確認が必要になることもあります。
フォールバックは裏側の挙動だけでなく、表のコミュニケーションまで含めて設計する、が現場で強いです。
失敗パターンを分類すると設計が速くなる
フォールバックは「失敗したら何かする」ですが、失敗の種類で最適解が変わります。実務でよくある分類は次の通りです。
タイムアウト(遅すぎて待てない)
多いです。落ちてはいないけど遅い状態。ここで重要なのは、待ち続けないこと。タイムアウトが長いと、サーバ側のリソースが詰まり、連鎖的に全体が重くなります。
一時的な失敗(リトライで回復しがち)
ネットワーク瞬断など。リトライは有効ですが、やりすぎると相手に負荷をかけて障害を悪化させます。回数よりも間隔設計が大事です。
恒久的な失敗(復旧に時間がかかる)
依存先が障害中のケース。リトライより、縮退運転や即フォールバックで「待たない設計」に切り替える方が被害が小さくなります。
データ不正(成功に見えるが中身が壊れている)
これが地味に厄介です。返ってきた値が想定外で、画面や処理が壊れます。フォールバックというより、バリデーションと安全なデフォルト設計が重要になります。
フォールバックの代表パターンと「使ってよい領域」
ここは誤解されやすいので、「どういうときに使いやすいか」をセットで整理します。
デフォルト値に置き換える
プロフィール画像のプレースホルダ、ランキングの空欄回避など、失敗しても業務的に意味が変わらないところで有効です。
注意点は、0や空配列のような「正常に見える値」を返すと、失敗と区別できなくなることです。運用や分析で困るので、内部的には「フォールバックした」フラグを残す設計がよく使われます。
キャッシュを返す
ニュース、天気、コンテンツ一覧など、「多少古くても許される」情報に強いです。一方で、在庫や価格、権限など「正確性が必須」の領域は危険です。ここはビジネス合意が必要になりやすいポイントです。
縮退運転する
「購入はできるが、おすすめは出さない」「検索は止めてカテゴリ導線だけにする」など、重要機能を守るために周辺機能を落とす設計です。障害時の生存率が上がります。
処理を後ろ倒しにして受け付ける
業務的に許される範囲なら強い手です。ただし、許されるかどうかが領域依存なので、合意と監査観点がセットになります。
ここからが本題:フォールバック後の整合性修復をどう設計するか
フォールバックでその場をしのげても、後で整合性が崩れていたら結局事故です。そこで重要になるのが「戻し方」です。
戻し方は大きく分けると 自動リカバリ と 再実行(イベント再送) です。ここを押さえると、実務の設計が一段上がります。
自動リカバリの基本は「再試行」ではなく「復旧に合わせた再開」
障害中にずっとリトライし続けると、相手が復旧した瞬間にリクエストが殺到して再炎上します。
よくある設計は次の組み合わせです。
- 指数バックオフ:失敗したら間隔を広げる
- ジッター:全員が同時に再試行しないように少し揺らす
- サーキットブレーカー:失敗が続くなら一定時間呼び出しを止める
この3つは、「障害を悪化させない」という意味でセット運用されがちです。
イベント再送設計で大事なのは「失敗を消さない」こと
「失敗したら諦める」だと、データ欠損になります。なので、失敗をキューやログとして保持し、後で再処理できるようにします。
よく使われる考え方は次の通りです。
- 失敗したイベントはDLQ(失敗用の置き場)に送る
- 復旧後にDLQから再処理する
- 再処理は冪等(何回やっても同じ結果)にする
この「冪等」は初心者にはとっつきにくいですが、例え話で言うと「同じボタンを2回押しても1回分だけ処理される」状態です。再送がある世界では必須になります。
二重送信・二重処理を防ぐには「冪等キー」が効く
イベント再送やリトライをやると、同じ処理が複数回走る可能性が出ます。そこで、処理単位に一意なキーを持たせて「このキーはもう処理済み」を判定できるようにします。
例えば「注文確定」なら注文ID、「メール送信」なら送信要求IDのような感じです。これがあると、再送しても安全になります。
コードはpython風に雰囲気だけ出すとこんなイメージです。(※あくまで風なので動きません。)
if already_processed(idempotency_key):
return OK
process()
mark_processed(idempotency_key)本質は、再試行しても壊れないようにしておくことです。
Outboxパターンで「DB更新とイベント送信のズレ」を防ぐ
実務でありがちな事故がこれです。
- DB更新は成功した
- でもイベント送信に失敗した
- その結果、別サービスが更新を知らない
これを避けるために、DB更新と同じトランザクション内で「送信予定イベント」をOutboxテーブルに書き、後から確実に送る設計があります。厳密な説明を省くと、要は「送るべきものをまず台帳に書く」方式です。
例えるなら、荷物を送る前に発送伝票を控えに残す感じです。配送が失敗しても、控えがあるからやり直せます。
Sagaで「跨る処理」を段階的に整合させる
複数サービスにまたがる処理では、全部を一気に確定できないことが多いです。そこで「段階的に進め、失敗したら補償処理で戻す」設計が使われます。
フォールバックで縮退した結果、途中で止まった処理があるなら、どこまで進んだかを状態として管理し、補償(取り消し)か再開を選べるようにするのが現実的です。
ここまで来ると難しそうに見えますが、考え方はシンプルです。
- 途中で止まるのは前提
- 止まった状態を記録する
- 再開か取り消しができるようにする
「戻し方」を設計するときのチェック観点
戻し方は抽象的になりやすいので、設計時に見ておくと事故りにくい観点をまとめます。
- フォールバックで受け付けた処理はどこに残るか(台帳、キュー、DLQなど)
- 再処理はいつ走るか(定期、手動、復旧検知など)
- 再処理が二重実行されても壊れないか(冪等性)
- 再処理が失敗し続けたときの置き場はあるか(DLQ)
- ユーザーへの表示はどう変わるか(保留中、反映待ちなど)
- 監視はどうするか(フォールバック発生、DLQ滞留、再処理失敗率など)
このあたりを事前に決めておくと、障害時に「戻せない」「調べられない」「誰も気づかない」の三重苦を避けられます。
実務でのポイント:フォールバック設計を現場で回すコツ

優先順位を明文化して、例外対応を減らす
機能を次のように分類しておくと、設計判断が速くなります。
- 絶対に落とせない(決済、認証、重要な更新)
- 落ちると不便だが致命傷ではない(検索、通知)
- 落ちても体験を大きく壊さない(おすすめ、装飾)
この分類があると、「この機能は縮退OK」「ここは明示エラー」と迷いにくくなります。
フォールバックは「静かに成功する」ので監視が必須
フォールバックが動くと、ユーザーからは正常に見えることがあります。だからこそ、運用側が気づく仕組みが必要です。
- フォールバック発生回数
- 依存先のタイムアウト率
- DLQ滞留件数
- 再処理失敗率
このあたりをメトリクスとして見られるようにすると、障害が「長引く」問題を減らせます。
UI文言は「正確さ」と「安心感」を両立させる
障害時の文言は、説明不足だと不安が増えますし、言い切りすぎると約束になってしまいます。
よく使われる落とし所は、「状況」「影響」「次の行動」を短く揃えることです。
- 現在、一部機能が利用しづらい状態です
- 影響:更新の反映に遅れが出ることがあります
- 対応:時間をおいて再度お試しください
このレベルでも問い合わせは減ります。
テストは「成功ケース」より「失敗ケース」を意図的に作る
フォールバックは普段動かないので、本番で初めて動くと壊れがちです。
- タイムアウトさせる
- 依存先を落とす
- キャッシュを空にする
- DLQを詰まらせる
こういう失敗を意図的に作って、画面・ログ・監視が想定通りかを確認するのが、実務では効きます。
一問一答:設計で迷いやすいところだけ短く
- キャッシュフォールバックは基本的に良い手?
-
良い手ですが領域次第です。古くても許される情報には強い一方、在庫や価格、権限などは古い値が事故になるので、ビジネス側と合意して線引きするのが安全です。
- 後回し処理のフォールバックはいつ検討すべき?
-
ユーザー体験を守りつつ業務的に許されるなら有効です。ただし規約・法務・監査の観点が絡むことが多いので、設計段階で合意を取り、ユーザーへの案内と整合性修復(戻し方)までセットにします。
- イベント再送って、結局リトライと同じ?
-
似ていますが狙いが違います。リトライは「その場で成功させたい」、再送は「失敗を記録して後で確実に処理する」です。再送があると、欠損を減らせます。
- 冪等性はなぜ必須?
-
再送やリトライがあると、同じ処理が複数回走る可能性が出ます。冪等性がないと二重課金や二重更新などの事故につながるので、現場では必須級の考え方です。
まとめ:フォールバックは「合意」と「戻し方」まで含めて完成する
フォールバック処理は、単に例外を拾って別の値を返すだけではありません。実務で本当に効くのは次の二点です。
1つ目は フォールバック方針をビジネス側と合意しておくこと
キャッシュや後回し処理は便利ですが、業務領域によってはリスクを伴います。技術的にできることと、やってよいことは別です。
2つ目は フォールバック後の整合性修復を設計しておくこと
自動リカバリ、サーキットブレーカー、DLQ、イベント再送、冪等性、Outbox、Sagaといった要素は、「戻せる」システムを作るための部品です。障害時に耐えるだけでなく、復旧後にきちんと正しい状態へ戻せることが、実務では強さになります。
フォールバックを「保険」ではなく「仕様」として扱う。さらに「その後どう戻すか」まで描く。この視点があるだけで、障害対応の質が一段上がります。

