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で必須
  • PayPalPayPal-Request-Idヘッダー
  • AWS — 多くのサービスでClientTokenパラメータ
  • Google CloudrequestIdクエリパラメータ

クライアントサイドのリトライロジック

1. 最初の試行前にIdempotency Keyを生成
2. キー付きでPOSTを送信
3. タイムアウトまたはネットワークエラー: 同じキーでリトライ
4. 409 Conflict: 操作は既に処理済み
5. 2xx: 成功(元のレスポンスまたは再生されたレスポンスの可能性)

ユースケース

決済ゲートウェイがPOSTでクレジットカード決済を処理します。クライアントがリクエストを送信しますが、レスポンスを受信する前に接続が切断されます。クライアントが同じIdempotency Keyでリトライします。サーバーがキーを認識し、カードに二重課金せずに元の成功レスポンスを返します。

試してみる — HTTP Method Reference

フルツールを開く