【ITニュース解説】I Built a Demo to Finally Understand Idempotency - Here's What Happened
2026年10月01日に「Dev.to」が公開したITニュース「I Built a Demo to Finally Understand Idempotency - Here's What Happened」について初心者にもわかりやすく解説しています。
ITニュース概要
「べき等性」とは、同じ操作を複数回行っても結果が常に同じになることだ。支払い処理などでネットワークエラーにより重複課金される問題を避けるため、リクエストに「べき等性キー」を付与する。これによりサーバーは初回処理を識別し、重複する後続リクエストには同じ結果を返すことで、システムの信頼性を確保する。
ITニュース解説
システム開発において、「べき等性」という概念は非常に重要である。これは、同じ操作を何度繰り返しても、一度だけ実行した場合と同じ結果になる性質を指す。特に、インターネットを介した通信が伴うシステム、例えばオンラインでの支払い処理などを開発する際には、このべき等性を理解し、適切にシステムに組み込むことが不可欠となる。もしこの保護がなければ、ユーザーは意図しない重複請求に見舞われたり、企業は多大なコストと信頼失墜に直面したりする可能性がある。
日常的な例で考えてみよう。エレベーターの「7階」ボタンを想像してほしい。このボタンを一度押しても、十度押しても、エレベーターが7階に向かうという結果は変わらない。決して、押した回数分だけエレベーターが呼ばれたり、何度も7階に停止したりすることはない。これはべき等な操作と言える。一方で、送金アプリで「500円をAさんに送る」という操作を三回繰り返した場合、Aさんは合計1500円を受け取ることになる。これはべき等ではない操作である。各リクエストが新たな指示として扱われ、その都度異なる結果が生じるからだ。
Webの世界では、HTTP通信のメソッドにもべき等性の性質が定められている。データを取得する「GET」メソッドは、何度実行してもサーバーの状態を変更しないため、べき等である。データを更新する「PUT」メソッドも、特定の値を「X」に設定するという操作は、一度行っても十度行っても最終的な状態は同じになるため、べき等だ。同様に、既に削除されたものを再度削除する「DELETE」メソッドも、最終的に「削除された状態」であることに変わりはないため、べき等である。しかし、新たなリソースを作成する「POST」メソッドは、実行するたびに新しいものが作成されるため、べき等ではない。この「POST」メソッドこそが、支払い処理のエンドポイントなどで問題を引き起こす張本人となる。
具体的に、どのような問題が起こるのか。ユーザーがオンラインストアで「支払い」ボタンをクリックしたとする。サーバーはこの支払いリクエストを受け取り、処理を開始する。しかし、その最中にネットワークが一時的に不安定になり、クライアント側には成功したという応答も、エラーだったという応答も届かず、ただタイムアウトするだけの状況が発生したとしよう。これを受けたクライアントソフトウェアは、一般的に「応答がなかったから、もう一度試してみよう」と自動的にリクエストを再試行する。これは、安定したサービスを提供するために適切に設計されたクライアントの標準的な挙動だ。
ここで問題が発生する。サーバーは最初の支払いリクエストを既に処理済みだったにもかかわらず、再試行された二回目、そしてもしかしたら三回目、といった新たなリクエストも、それぞれ独立した新しい支払いとして処理してしまう可能性があるのだ。結果として、ユーザーのクレジットカードには、一度の購入に対して三回分の請求が記録されてしまう。ユーザーはすぐにサポートセンターに連絡し、企業は二時間もかかる返金処理に追われることになる。このような状況が大規模に発生すれば、クレジットカード会社からのチャージバック(顧客からの異議申し立てによる返金)対応に追われる悪夢のような事態に陥りかねない。プログラムのコードで言えば、保護のない支払い処理のエンドポイントでは、リクエストが来るたびに新しい取引IDを生成し、それぞれをデータベースに保存してしまう、という動きになる。同じ情報で複数回リクエストしても、毎回異なるIDの記録が生まれるのだ。
この問題の解決策が「べき等性キー」の導入である。これは、クライアントが意図する個々の操作に対し、ユニークな識別子となるキーを生成し、そのキーをリクエストヘッダーなどと共にサーバーへ送信する方法だ。サーバーはこのべき等性キーを利用して、「このキーを持つリクエストは以前に受け取っている」と認識できるようになる。もし同じキーを持つリクエストが複数回届いた場合、サーバーは二回目以降のリクエストに対しては実際に支払い処理を行うことなく、最初にそのキーで処理した際の結果をそのまま返す。これにより、ユーザーのクレジットカードは一度しか請求されず、再試行が行われたとしても常に同じ結果が返されることが保証される。
べき等性キーを導入した支払い処理のロジックは非常にシンプルである。まず、サーバーは受け取ったべき等性キーをチェックする。もしそのキーが既に処理済みとして保存されていれば、保存しておいた以前の結果をすぐにクライアントに返す。これは実質的に、支払い処理をスキップしていることになる。もしキーが初めて受け取ったものであれば、サーバーは通常の支払い処理を実行し、その処理結果とべき等性キーを関連付けて保存する。そして、その結果をクライアントに返す。この二段階のシンプルなロジックによって、たとえネットワークが不安定で再試行が繰り返されたとしても、実際の課金処理は一度しか実行されないことが保証されるのだ。
この仕組みを導入する上で、いくつか重要なポイントがある。まず、べき等性キーはクライアント側で生成されるべきだ。もしサーバーがキーを生成してしまうと、再試行のたびに新しいキーが発行され、サーバーが重複したリクエストを識別できなくなり、べき等性の保護が無意味になってしまうからである。次に、べき等性キーは単一の意図された操作に限定して使用されるべきだ。「ユーザー123による支払い456」といった具体的な情報を含むキーが理想的である。もし「私の支払いキー」のような汎用的なキーを使い回すと、誤って以前の全く異なる支払いの結果が返されてしまう危険性がある。さらに、実際にシステムを運用する上では、べき等性キーとその結果を保存する場所も重要だ。一時的なメモリ上ではなく、サーバーが再起動してもデータが失われないよう、Redisのような高速なデータストアやデータベースに永続的に保存する必要がある。多くの場合、べき等性キーは一定時間(例えば24時間)経過したら不要になるため、有効期限(TTL: Time To Live)を設定して自動的に削除されるように運用するのが一般的だ。
このようなべき等性のパターンは、一度理解すると、あらゆる場所でその必要性や適用例を見つけることができる。StripeやM-Pesa、GitHubのAPIやTwilioなど、多くの有名なサービスがAPI設計においてべき等性キーを標準的な機能として提供している。これは決して高度な概念ではなく、新しいリソースを作成するエンドポイントを構築する際には常に考慮すべき、基本的ながら非常に強力なツールなのである。
このべき等性への対策を怠ると、上述したような重複請求、重複注文、さらには重複メール送信といった、現実世界に影響を及ぼす重大なバグにつながる。これらのバグは、開発段階のテスト環境ではネットワークが安定していることが多いため、見過ごされがちである。そして、いざ本番環境で大規模に稼働し、現実の不安定なネットワーク状況に直面したときに初めて顕在化し、ユーザーからの苦情や企業の評判に関わる問題を引き起こすのだ。
もしこの概念をより深く理解したいのであれば、実際に手を動かして試してみるのが一番だ。GitHubで公開されているデモプロジェクトを自分のコンピューターで動かし、保護のない支払いエンドポイントと、べき等性キーで保護された支払いエンドポイントの両方で、同じリクエストを複数回実行してみると良い。支払いIDが毎回変わるのか、それとも常に同じ支払いIDが返ってくるのかを自分の目で確認する体験は、概念を読んだだけでは得られない深い理解をもたらすだろう。