Webhook の冪等性は event ID を一意制約付きテーブルに記録して担保する
バックエンド
Webhook
設計判断
多くの webhook(決済プロバイダ等)は at-least-once 配信で、同じイベントが再送される。受信ハンドラが冪等でないと、再送のたびにレコード重複作成や権限の二重付与などの実害が出る。
設計
- プロバイダが各イベントに付与する一意な event ID を、UNIQUE 制約付きの「処理済みイベント」テーブルに記録する。
- ハンドラ冒頭で event ID の登録を試み、
INSERT ... ON CONFLICT DO NOTHINGの影響行数で「初回 or 既処理」を原子的に判定。既処理なら副作用を起こさず早期 return(2xx 相当)。 - 状態を変える複数の書き込みは1トランザクションで括る。
判断基準・落とし穴
- 「最新1件を見るから重複しても平気」は危険。重複行が残ると後続の検索や状態判定がどの行を返すか不定になる。
- 受信処理で 5xx を返すとプロバイダが延々リトライする。処理不能でも『記録済み/対象なし』として扱えるものは 2xx を返しリトライ嵐を防ぐ(重複作成は一意制約で別途防ぐ)。
- 既存テーブルに後付けで UNIQUE 制約を足す場合は、既存重複の解消が前提(別途検出が必要)。
検証方法
同一 event ID を2回送り、2回目が副作用なく早期 return すること、状態変更が1回だけ適用されることをテストする。