Idempotency KeyによるPOSTの冪等化
Idempotency Keyを使用してPOSTリクエストをリトライ安全にする方法を学びます。リソースの重複作成や二重課金を防止します。
Advanced
詳細な説明
非冪等POSTの問題
POSTは冪等ではありません — 同じリクエストを2回送信すると2つのリソースが作成されます。これは以下のシナリオで危険です:
- 決済処理(二重課金)
- 注文確定(重複注文)
- メール送信(重複通知)
Idempotency Key
Idempotency Keyはリクエストと共に送信される一意の識別子です。サーバーはキーをレスポンスと共に保存します。同じキーが再度送信されると、サーバーはリクエストを再処理せずに保存されたレスポンスを返します。
実装
POST /api/payments HTTP/1.1
Content-Type: application/json
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
{
"amount": 5000,
"currency": "USD",
"customer_id": "cus_123"
}
最初のリクエスト: サーバーが支払いを処理し、結果をIdempotency Keyで保存し、201 Createdを返す。
リトライ(同じキー): サーバーが保存された結果を見つけ、支払いを再処理せずに同じ201 Createdレスポンスを返す。
サーバーサイドロジック
1. Idempotency-Keyヘッダー付きリクエストを受信
2. キーがストレージに存在するか確認
- ある場合: 保存されたレスポンス(HTTPステータス+ボディ)を返す
- ない場合: リクエストを通常通り処理
3. レスポンスをキーと共に保存(TTL: 24-48時間)
4. レスポンスをクライアントに返す
キー生成のベストプラクティス
| アプローチ | 例 | 利点 |
|---|---|---|
| UUID v4 | 550e8400-e29b-41d4-a716-446655440000 |
シンプル、普遍的にユニーク |
| 複合 | user-123:order:2026-01-15T10:30:00Z |
決定的、デバッグしやすい |
| ハッシュ | sha256(request_body + timestamp) |
コンテンツベースの重複排除 |
Idempotency Keyを使用するAPI
- Stripe — Payment Intentsで必須
- PayPal —
PayPal-Request-Idヘッダー - AWS — 多くのサービスで
ClientTokenパラメータ - Google Cloud —
requestIdクエリパラメータ
クライアントサイドのリトライロジック
1. 最初の試行前にIdempotency Keyを生成
2. キー付きでPOSTを送信
3. タイムアウトまたはネットワークエラー: 同じキーでリトライ
4. 409 Conflict: 操作は既に処理済み
5. 2xx: 成功(元のレスポンスまたは再生されたレスポンスの可能性)
ユースケース
決済ゲートウェイがPOSTでクレジットカード決済を処理します。クライアントがリクエストを送信しますが、レスポンスを受信する前に接続が切断されます。クライアントが同じIdempotency Keyでリトライします。サーバーがキーを認識し、カードに二重課金せずに元の成功レスポンスを返します。