Outbox パターン

DB の変更とイベント発行を 1 つのトランザクションで保証するメッセージング信頼性パターン

設計パターンイベント駆動

Outbox パターンとは

Outbox パターンは、DB の変更とイベント発行を 1 つのトランザクションで保証するパターンである。DB に書き込んだがイベントが発行されない (またはその逆) という不整合を防ぐ。

問題: 二重書き込み

❌ DB 書き込み + イベント発行が別トランザクション:
  1. DynamoDB に注文を保存 → 成功
  2. EventBridge にイベント発行 → 失敗
  → 注文は保存されたがイベントが失われる

Outbox パターンの仕組み

1. DynamoDB に注文 + Outbox レコードを TransactWrite
2. DynamoDB Streams が Outbox の変更を検知
3. Lambda が Outbox レコードを読み取り、EventBridge に発行
→ DB 書き込みとイベント発行が原子的

DynamoDB での実装

await db.transactWrite({
  TransactItems: [
    { Put: { TableName: 'orders', Item: { PK: `ORDER#${id}`, ...order } } },
    { Put: { TableName: 'outbox', Item: {
      PK: `OUTBOX#${id}`,
      eventType: 'OrderCreated',
      payload: JSON.stringify(order),
      createdAt: Date.now(),
    } } },
  ],
});
// 両方が成功 or 両方が失敗 (原子性)

Outbox vs 直接イベント発行

観点 直接発行 Outbox
原子性 ❌ (二重書き込み) ✅ (1 トランザクション)
複雑さ 低い
遅延 低い やや高い (Streams 経由)
信頼性 低い 高い

いつ使うか

ケース 推奨
イベントの欠損が許容できない ✅ Outbox
最終的に整合すれば十分 直接発行 + リトライ
金融取引、注文処理 ✅ Outbox

Outbox パターンの背景や設計思想は関連書籍に詳しい。

関連用語