冪等性とは何か
冪等性(idempotency、べきとうせい)とは、同じ処理を1回実行した場合と、複数回繰り返し実行した場合とで、最終的な結果(状態)が変わらないという性質のことです。プログラミング、特にAPI設計の文脈でよく使われる考え方です。
「エレベーターのボタン」に例えると
身近な例で考えると、エレベーターの呼び出しボタンが分かりやすいです。ボタンを1回押しても、慌てて3回連打しても、結果として「エレベーターが来る」という状態は変わりません。3回押したからといって、エレベーターが3台来るわけではないはずです。冪等性のあるシステムは、これと同じように「何度実行されても、結果が1回分と同じ」になるよう設計されています。
なぜ重要なのか:ネットワークの「不確実性」への備え
インターネット越しの通信では、リクエストを送った後に通信が不安定になり、処理が成功したのか失敗したのか、送信側からは正確に判断できない場面があります。この時、「念のため、もう一度送信する」という再送処理は、実務でよく行われる対応です。
しかし、もし決済処理のようなシステムが冪等性を考慮せずに作られていた場合、この再送によって「同じ決済が2回実行されてしまう」という深刻な問題が起こり得ます。
図で見る、再送信時の挙動の違い
冪等性の有無によって、再送信した時の結果がどう変わるのか、図で確認してみましょう。
「冪等キー」という解決策
この問題に対応するため、多くのAPIでは「冪等キー(Idempotency Key)」という仕組みが使われています。リクエストを送る側が、そのリクエスト固有の識別子(キー)を発行して一緒に送信し、サーバー側は「このキーはすでに処理済みかどうか」を記録しておきます。同じキーのリクエストが再び届いた場合、サーバーは新しく処理を行わず、前回と同じ結果をそのまま返すことで、意図しない二重処理を防ぎます。
HTTPメソッドと冪等性の関係
Web開発の基礎となるHTTPの仕様でも、各メソッドに冪等性の有無が定義されています。MDN Web Docsの解説によれば、GETやPUT、DELETEといったメソッドは冪等であるとされる一方、POSTメソッドは冪等ではないメソッドに分類されています。これは、POSTが一般的に「新しいデータを作成する」目的で使われることが多く、同じリクエストを2回送ると、2件のデータが作られてしまう可能性があるためです。だからこそ、POSTで実装される決済や注文確定などの処理では、開発者が意識的に冪等性を持たせる工夫が必要になります。
実際の開発現場でよくあるつまずき
- 「再送すれば直るだろう」という安易な対応で、決済APIをそのまま2回叩いてしまい、二重請求が発生する
- 冪等キーを導入したものの、キーの有効期限を短く設定しすぎて、想定より早く「別の新しいリクエスト」として扱われてしまう
- フロントエンド側で「送信中」のローディング表示を出し忘れ、利用者が「反応がない」と勘違いして、送信ボタンを何度も連打してしまう
3つ目のように、システム内部の設計だけでなく、利用者側の操作(連打)によって意図せず同じリクエストが複数回送られてしまうケースも、現場では頻繁に起こります。
GETリクエストが冪等でも、キャッシュには注意
余談ですが、GETリクエストが冪等であることと、その結果が常に同じ内容を返すことは、厳密には別の話です。サーバー側のデータが更新されていれば、同じGETリクエストでも返ってくる中身は変わります。冪等性が保証しているのは、あくまで「サーバー側の状態が、リクエストの回数によって余計に変化しない」という点であることを理解しておくと、混同を防げます。