uniflow
KO / EN
Dev·개념·2026-06-30

What Is Idempotency? How to Stop Duplicate Payments and Orders

Press the pay button twice — does the customer get charged twice? Idempotency is the concept that prevents this common failure. Here is what it means, how HTTP methods differ, and how an idempotency key stops duplicate payments and orders.

Press Pay Twice — Does the Customer Pay Twice?

When an online payment stalls for a second, almost everyone presses the button again. So does the customer actually get charged twice? In a well-built system, pressing twice still charges once. The concept that guarantees this is idempotency.

It sounds like developer-only jargon, but it is a problem product managers and operations teams hit even more often. "Refund a duplicate charge," "two orders came in for one purchase," "points were credited twice" — these incidents all live in the gap where idempotency is missing. This post covers what idempotency is, why it matters most for payments and orders, and what you actually need to decide in practice.

What Idempotency Really Means — Same Result, However Many Times

Idempotency, in one line, is the property that sending the same request once or many times produces the same result as sending it once. The word comes from math, but the idea is intuitive. A light switch makes it clear.

  • "Turn the light off" is idempotent. If it is already off, turning it off again still leaves it "off." Ten presses, one result.
  • "Toggle the light" is not idempotent. Each press flips the state, so the result changes every time.

Applied to payments: "set this order to paid" can be designed to be idempotent, but "add one new charge" is not idempotent if left as-is. Send it twice and you get two charges.

Idempotent vs Non-Idempotent Operations

The key is the difference between setting state to a specific value and adding something new. Operations that set a value (replace, delete) are naturally idempotent; operations that add (create, accumulate) are not, unless you make them so. That is why the dangerous side is always the "add new" actions — payments, orders, point credits.

Idempotency Through HTTP Methods

Web APIs already draw this line at the method level. Here is what the standard (RFC 9110) defines as idempotent.

MethodIdempotentMeaning
GETYesRead — the data does not change no matter how often you read
PUTYesFull replace — overwriting with the same value gives the same result
DELETEYesDelete — deleting twice still leaves the "gone" state
POSTNoCreate — sending twice creates two records (duplicate charge!)
PATCHNoPartial update — accumulating changes shift the result

The catch is that "create" actions like payments and orders are almost always POST, and POST is not idempotent by standard. If the network drops and the client retries, or the user presses twice, you simply get two records. That is why a separate safeguard is needed.

How Payments and Orders (POST) Are Protected — The Idempotency Key

The standard way to make a non-idempotent POST idempotent is the idempotency key (Idempotency-Key). Payment APIs like Stripe and Adyen all offer it, and the IETF is standardizing it as an HTTP header — it is a well-settled pattern.

How It Works — One Key Absorbs Duplicates

The mechanism is three simple steps.

  1. The client sends a unique key (usually a UUID) along with the request.
  2. The server stores the result under that key. If the key is new, it processes normally.
  3. If the same key arrives again, it does not reprocess — it returns the original stored result.

A request looks roughly like this.

Advertisement본문 중간 · 반응형본 도메인에서만 게재

[code lang="text"] POST /orders Idempotency-Key: 8f3a1c2e-4b6d-49a1-9b7d-2e5c1a0f7d33

First request → create the order, store the result with the key Same key again → no new order; return "already processed + same result" [/code]

Now whether the user presses twice or the client auto-retries after a timeout, the result is always one record. Because it makes retries safe, idempotency pairs with fallback design as one of the two pillars of system reliability.

What Product Managers Need to Decide

Developers implement idempotency, but deciding what should be idempotent is often a product and operations call. These four are worth settling at the spec stage.

DecisionQuestion to answer
Who generates the keyDoes the client create the UUID, or does the server issue it?
Retention windowFor how long is the same key treated as "the same request"? (Stripe uses 24 hours)
Response on duplicateReturn the original stored result, or signal an error?
ScopePayments and orders only, or also point credits and notifications?

That last row is the one most often missed. Teams guard the payment but let "credit points" and "push notification" fire twice. The full set of side effects from a single user action should fall under the idempotency scope.

When You Need to Care About Idempotency

Not every request needs an idempotency key. Reach for it when:

  • The action leaks money, inventory, or trust if it runs again (payment, order, refund, transfer, point credit)
  • The client auto-retries the call (a re-request after a network timeout)
  • The flow integrates with external systems where a duplicate becomes an incident immediately

Conversely, a plain read (GET) or a state change designed to be idempotent (PUT/DELETE) is already safe and needs no extra machinery. Deciding "what to guarantee" centrally, up front, is the same mindset behind a closed-loop operation.

A System That Is Safe to Press Twice

Idempotency is not a grand theory — it is a very practical safeguard that keeps "the user pressed twice" from becoming an incident. The core is simple: the same request, however many times it arrives, has the same effect as once. For add-type actions like create, pay, and credit, attach an idempotency key to absorb retries and double-clicks.

If you are a product manager, write "what happens if this action runs twice?" into the spec. If you are an engineer, make the idempotency key a default on every payment and order endpoint. A system that is safe to press twice is, in the end, the foundation of trust that lets users confidently press pay.

Advertisement글 최하단 · 띠배너본 도메인에서만 게재