エレベーターの前でボタンを一度押したのに不安で、もう何度か押した経験があるでしょう。すでに点灯しているのに、さらに押してもエレベーターが二台来ることはありません。反対に、オンライン決済画面でボタンを二度押してしまい、二度課金されないか胸をざわつかせたこともあるでしょう。同じ動作なのに一方は安全で一方は危険な理由を説明する概念が、まさに冪等性です。
冪等性(Idempotence)とは、ある動作を一度しても何度しても、最初の一度の結果からそれ以上変わらない性質をいいます。簡単に言えば「やり直しても、すでに終わったことがさらに大きくならない」という意味で、接続が切れたりリクエストが重複したりしやすいコンピュータの世界では特に重要に扱われます。
本資料では、冪等性という名前がどこから来たのか、日常の事例はどう分かれるのか、HTTPがこの概念をどう約束にしているのか、そして重複リクエストを安全に扱う設計とよくある誤解まで、順に見ていきます。
二度しても一度と同じ動作の理
同じ力という意味、数学から来た名前

この用語は、1870年にアメリカの数学者ベンジャミン・パース(Benjamin Peirce)が線形結合代数(Linear Associative Algebra)を扱った文章で作ったものとされています。「同じ」を意味するidemと「力」を意味するpotenceを合わせた語で、文字どおり「同じ力を持つ」という意味です。パースは、二乗やそれ以上の冪乗をしても自分自身になる代数的対象にこの名前を付けました。
(1) 数学的定義
関数fを二度適用した結果が一度適用した結果と同じであることを指し、f(f(x)) = f(x)と書きます。
(2) 代表的な関数
絶対値、小数点以下を切り捨てる床関数、天井関数、入力をそのまま返す恒等関数がこの性質を持ちます。
(3) コンピュータに渡ってきた意味
副作用のある作業でも、何度呼び出した後のシステム状態が一度呼び出した後と同じなら、冪等と呼びます。
ここで注目すべきは、「応答が同じ」ではなく「状態がそれ以上変わらない」が基準だという点です。この違いを見落とすと、冪等性をほかの概念と混同し続けてしまいます。
日常のボタンで見分ける冪等と非冪等

エレベーターの呼び出しボタンや横断歩道のボタンは、最初に押すと「要求中」の状態になり、その要求が処理されるまで何度押しても何も起きません。ドア閉ボタンも決まったスケジュールどおりに閉まるので、何度押しても同じです。しかしドア開ボタンは押すたびに待ち時間が延びるので、冪等ではありません。
- 照会(Lookup):顧客の名前と住所を読むことはデータを変えないので冪等です。
- 設定(Assignment):住所を特定の値に変えるという要求は、何度送っても最終の住所が同じなので冪等です。
- 注文(Order Placement):注文を入れるという要求は、送った回数だけ注文が生まれることがあり、冪等ではありません。
- 取消(Cancellation):特定の注文を取り消すという要求は、何度送っても注文が取り消された状態のままなので冪等です。
同じ「ボタン押し」でも、状態を決める動作なのか、状態に何かを足す動作なのかで運命が分かれます。
HTTPが定めたメソッドごとの約束

ウェブの規約であるHTTPの標準文書(RFC 9110)は、同じ要求を何度送ったときのサーバーへの意図された効果が、一度送ったときと同じメソッドを冪等と定義します。
(1) 読み取り要求
GET、HEAD、OPTIONS、TRACEは読み取りだけを求める安全なメソッドであり、すべて冪等です。
(2) PUTとDELETE
PUTは対象の状態を送った内容に定め、DELETEは対象を消します。何度送っても終わった状態が同じなので、冪等と規定されています。
(3) POSTとPATCH
POSTは内容の処理を受け手に任せるので、二度送ると注文が二件できることがあります。PATCHも冪等は保証されません。
この区分が実際に使われるのは再試行です。接続が切れて応答を読めなかったとき、冪等な要求はクライアントが自動で再送しても構いませんが、冪等でない要求は、元の要求が適用されなかったと分かる手段がなければ自動再試行しない方が望ましいと標準は勧めています。また冪等は応答が同じという約束ではないので、削除を二度目に送ると初回と違って「なし」の応答が返っても問題ありません。

重複要求を扱う設計とよくある誤解

それでは、冪等でないPOSTをどうしても再送しなければならないときはどうするのでしょうか。広く使われる方法が、要求ごとに固有の値を付ける冪等性キーです。決済サービスStripeは、要求にIdempotency-Keyヘッダーを付けられるようにしました。キーは最大255文字で、無作為なUUIDのような値を推奨し、同じキーで再び来た要求には最初の要求のステータスコードと本文をそのまま返します。キーは最低24時間が過ぎると消されることがあり、同じキーに別の内容が来るとエラーとして扱います。メッセージが二度以上到着しても同じ結果を出すイベント処理システムも、同じ発想の上に立っています。
- 応答(Response):冪等は応答が同じという意味ではなく、サーバーの状態がそれ以上変わらないという意味です。
- 副作用(Side Effect):サーバーが要求の記録を残すことまで数えず、意図した効果だけを基準にします。
- 合成(Composition):冪等な段階をつなげても、全体が冪等という保証はありません。
- 例(Example):変数が3のとき「読む、5に変える、読む」を一度実行すると3と5が出て、二度目には5と5が出ます。
二度押しても大丈夫にする仕事は、利用者の注意深さに頼る代わりに、システムが自ら安全になるよう設計することです。やり直しても同じ結果になるよう最初から動作を設計する心、それが冪等性の第一歩です。