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 パターンの背景や設計思想は関連書籍に詳しい。