「DBが落ちたら全部止まる」、それ本当に仕方ない?
深夜にSlack通知が鳴る。「本番DBが応答しません」。ユーザーには500エラーの白い画面。復旧まで30分、その間の売上はゼロ。こんな経験、あるいは想像するだけでも胃が痛くなりますよね。
でも考えてみてください。DBが落ちた時に「何も返せない」のと「キャッシュから古いデータでも返せる」のでは、ユーザー体験がまるで違います。後者の考え方が、フォールバック(fallback)です。
本記事では、DBフォールバックの基本概念から、実務で使える3つの実装パターン、やってはいけないアンチパターンまでを解説します。
DBのフォールバックとは? ― 障害時の「代替手段」で動き続ける仕組み
フォールバック(fallback)は、「fall(落ちる)」+「back(後ろに)」で、「本来の手段が使えない時に、代替手段に切り替える」という意味です。
【フォールバックなし】
リクエスト → DB問い合わせ → DB障害 → 500エラー → ユーザーに白い画面
【フォールバックあり】
リクエスト → DB問い合わせ → DB障害 → キャッシュから返す → ユーザーには古いけどデータが見える完璧なデータを返せなくても、「何かしら返す」ことでサービスの体験を維持するのがフォールバックの目的です。100点が無理なら80点でいい、0点だけは避ける、という設計思想です。
どんな場面で必要?
フォールバックが効くのは、「多少古い・不完全なデータでもユーザーに価値がある」場面です。
| 場面 | フォールバック | 理由 |
|---|---|---|
| 商品一覧ページ | ✅ 有効 | 5分前のデータでも表示できれば離脱を防げる |
| ダッシュボードの集計値 | ✅ 有効 | リアルタイムでなくても直近の値で十分判断できる |
| 決済処理 | ❌ 不適切 | 古いデータで決済すると二重課金や金額不整合のリスク |
| 在庫数チェック | ⚠️ 要検討 | 古い在庫数で受注すると欠品になるが、表示だけなら許容範囲 |
ポイントは、「読み取り」にはフォールバックが効きやすく、「書き込み」には慎重であるべきということ。決済や在庫確定のような整合性が必須の処理は、フォールバックではなくリトライやキューイングで対応するのが正解です。
フォールバックの3つの実装パターン
パターン1:キャッシュフォールバック(最も一般的)
正常時にキャッシュを更新しておき、DB障害時にはキャッシュから返す。Redisやインメモリキャッシュとの組み合わせが定番です。
// キャッシュフォールバックの基本パターン
import Redis from 'ioredis';
import { Pool } from 'pg';
const redis = new Redis();
const db = new Pool();
async function getProducts(): Promise {
try {
// 1. まずDBから最新データを取得
const result = await db.query('SELECT * FROM products WHERE active = true');
const products = result.rows;
// 2. 成功したらキャッシュを更新(TTL 5分)
await redis.set('products:active', JSON.stringify(products), 'EX', 300);
return products;
} catch (error) {
console.error('DB query failed, falling back to cache:', error);
// 3. DB障害時はキャッシュから返す
const cached = await redis.get('products:active');
if (cached) {
return JSON.parse(cached);
}
// 4. キャッシュもなければエラー
throw new Error('DB and cache both unavailable');
}
} この実装のポイントは、正常時に毎回キャッシュを更新していること。DB障害が起きた時にキャッシュが空だと意味がないので、「常にキャッシュを温めておく」のが重要です。
パターン2:リードレプリカフォールバック
プライマリDBが落ちた時に、リードレプリカ(読み取り専用の複製DB)に切り替えるパターン。キャッシュと違いデータの鮮度がほぼリアルタイムなのがメリットです。
// リードレプリカフォールバック
const primaryDb = new Pool({ host: 'db-primary.example.com' });
const replicaDb = new Pool({ host: 'db-replica.example.com' });
async function queryWithFallback(sql: string, params?: any[]) {
try {
return await primaryDb.query(sql, params);
} catch (error) {
console.warn('Primary DB failed, switching to replica:', error);
return await replicaDb.query(sql, params);
}
}AWS RDSやAurora、Cloud SQLなど主要なマネージドDBサービスはリードレプリカを簡単に追加できます。コスト面でレプリカを常時稼働させる余裕があるなら、最も信頼性の高いフォールバック手段です。
パターン3:静的データフォールバック(最後の砦)
DBもキャッシュも死んだ場合の最終防衛線。JSONファイルやCDNに置いた静的データを返します。
// 静的データフォールバック(最後の砦)
import fallbackData from './fallback/products.json';
async function getProductsSafe(): Promise {
try {
return await getProductsFromDB();
} catch {
try {
return await getProductsFromCache();
} catch {
// DB・キャッシュ全滅 → 静的データで最低限の表示を維持
console.error('All sources failed, returning static fallback');
return fallbackData;
}
}
} ECサイトなら「定番商品だけでも表示する」、SaaSなら「メンテナンス中の案内ページを出す」など、0点を避けるための最低限のデータを用意しておくイメージです。
やってはいけないアンチパターン
アンチパターン1:書き込み処理にフォールバックを適用する
「DBが落ちてるからキャッシュに書いておこう」は非常に危険です。DB復旧後にキャッシュとDBの整合性が取れなくなり、データ不整合が連鎖します。書き込みが失敗する場合は、メッセージキュー(SQS、RabbitMQ等)に入れて後で再処理するのが安全なパターンです。
アンチパターン2:フォールバックデータであることを隠す
キャッシュや静的データを返している時に、ユーザーに何も伝えないのはNGです。「最終更新: 5分前のデータを表示しています」のような表示を出しておけば、ユーザーはデータの鮮度を判断できます。古いデータを最新だと誤認させるのが一番まずい。
アンチパターン3:フォールバックのテストをしていない
フォールバックは障害時にしか動かないコードなので、テストされないまま放置されがちです。いざ障害が起きた時に「フォールバック先のキャッシュが空だった」「接続設定が古くて繋がらない」では本末転倒。定期的に意図的にDBへの接続を切ってフォールバックが動くか確認しましょう。
DB障害対策をさらに深める関連記事
フォールバックの設計を理解したら、DB運用やインフラ設計の周辺知識も固めておきましょう。
データベース・インフラ
- psqlとは?PostgreSQLをコマンドラインで操作する基本コマンドと実践的な使い方 – フォールバックの動作確認やDB障害のシミュレーションにpsqlのコマンド操作が役立ちます
- 無料で使えるPostgreSQLサービス8選を比較!2025年版おすすめ – リードレプリカを含むマネージドDB選定の参考に
- AWS CLIで開発が爆速になる!セットアップからCloudWatch・Lambda活用まで実用コマンド付き – RDSのフェイルオーバー確認やCloudWatchアラーム設定に
設計・運用
- 「全部POSTでよくない?」がモヤる人へ|HTTPメソッド使い分けの正論と現場のリアル – 読み取り/書き込みの設計判断はフォールバック戦略にも直結します
- IaC(Infrastructure as Code)とは?インフラをコードで管理する3つのメリット – リードレプリカやキャッシュサーバーの構成をコードで管理する考え方
まとめ:100点が無理なら80点を返す、0点だけは避ける
本記事のポイントを整理します。
- フォールバックとは、DB障害時に代替手段(キャッシュ・レプリカ・静的データ)でサービスを継続する設計パターン
- 読み取り処理に有効。書き込みにはフォールバックではなくキューイングで対応
- 3つのパターン:キャッシュフォールバック(定番)、リードレプリカ(高信頼)、静的データ(最後の砦)
- アンチパターンに注意:書き込みへの適用、データ鮮度の非表示、テスト不足
DBは落ちます。どんなに堅牢な構成でも、ゼロダウンタイムは幻想に近い。大事なのは「落ちない」ことではなく、「落ちた時にどう振る舞うか」を事前に設計しておくこと。フォールバックは、その設計の第一歩です。
