Free sample lesson · Idempotency 完全指南:Retry-Safe API 設計實務
什麼是 idempotent operation
Lesson 1 of the Wondering course Idempotency 完全指南:Retry-Safe API 設計實務
The Repeat-Safe Operation
Press an elevator button once. Press it five more times. The elevator still comes once.
That is an idempotent operation: running it again does not change the result beyond the first run.
The opposite is everywhere too. Press "Pay" five times on a broken checkout page and you may be charged five times.
- Elevator button
- Broken checkout
Idempotency is the property that makes repetition harmless.
The Definition, Precisely
The formal idea is simple. Applying the operation once gives the same final state as applying it many times.
Notice what is not claimed. Idempotency does not mean nothing happens on the repeat. Work may still be done.
It only means the observable end state stops changing after the first successful run.
- Start: The light switch begins in the OFF state.
- First run: The operation sets the switch to ON, so the state changes.
- Second run: The operation sets ON again and the state stays ON.
- Tenth run: The final state is still ON, identical to after the first run.
So "set the light switch to ON" is idempotent. "Flip the light switch" is not.
Why Retries Exist At All
Networks fail in an awkward way. A request goes out and no answer comes back.
You now face a question you cannot answer from your side. Did the server never receive it, or did it succeed and the reply got lost?
Both look identical to the caller.
- Send request
- Reply received?: The caller waits for an answer from the server.
- Result known
- Outcome unknown: The request may have never arrived, or it succeeded and the reply was lost.
- Retry
That ambiguity is why retries exist, and why they are dangerous without idempotency.
Idempotency Makes Retry Safe
Here is the connection. If the operation is idempotent, you do not need to know whether the first attempt succeeded.
Retry it. If the first one worked, the retry changes nothing. If it did not, the retry does the work.
Either way you land in the same correct state.
- Send request: The caller issues an idempotent operation.
- No reply: A timeout leaves the outcome unknown.
- Retry: The caller sends the same operation again without checking first.
- State unchanged: If the first attempt already succeeded, the repeat adds nothing.
Without idempotency, the same retry is a gamble between a lost update and a duplicate one.
Spotting It In Your Own Code
Ask one question of any operation: if this runs twice, does the end state differ?
Idempotent: set a status to "paid". Delete a record by ID. Read a value. Overwrite a file with the same content.
Not idempotent: add $100 to a balance. Append a row. Increment a counter. Send an email.
- Set status paid
- Delete by ID
- Add $100
- Send email
The pattern is that absolute assignments repeat safely, while relative changes accumulate.
Making Things Idempotent
Most useful operations are not naturally idempotent. You can often give them the property.
The common move is an idempotency key: the caller attaches a unique ID to the request.
The server records that ID with its result. A repeat arrives, the server recognizes the key and returns the stored result instead of doing the work again.
- Attach ID: The caller generates a unique ID and sends it with the request.
- Check store: The server looks up whether it has already seen that key.
- Do work once: If the key is new, the server performs the operation and records the key with its result.
- Replay result: If the key is known, the server returns the stored result without repeating the work.
This is how payment APIs let you retry a charge without charging twice.
Carrying It Forward
Idempotency is a design precondition, not an afterthought. Retries, queues, and at-least-once delivery all assume it.
Any system that can deliver a message more than once needs handlers that tolerate repeats.
So when you design an endpoint or a job, ask early: what happens if this runs twice?
If the honest answer is "something bad", add a key, use absolute assignment, or accept that you cannot safely retry.
Check yourself
An operation is idempotent if running it repeatedly produces the same observable final state as running it once.
- True
- False
Answer: True
This is true. Idempotency concerns the final observable state, not whether the server performs no work during later runs.
Setting a status to "paid" is _____, incrementing a counter is _____, and attaching a unique request identifier uses an _____.
Answer: Setting a status to "paid" is idempotent, incrementing a counter is not idempotent, and attaching a unique request identifier uses an idempotency key.
Absolute assignments such as setting a status repeat safely. Relative changes such as increments accumulate. An idempotency key lets a server recognize a repeated request and reuse its stored result.
A client sends a payment request, but the response is lost. The client cannot tell whether the server never received the request or completed the payment successfully. Why is retrying safe when the payment operation is idempotent?
- The retry is guaranteed to reach the server twice, so both attempts can be compared.
- The retry either completes missing work or leaves the successful result unchanged.
- The lost response proves that the server did not process the original request.
- The server automatically reverses any duplicate payment after the retry.
Answer: The retry either completes missing work or leaves the successful result unchanged.
With idempotency, a retry either performs the payment if the first attempt failed or leaves the already-correct state unchanged if the first attempt succeeded. The client does not need to resolve the network ambiguity first.
Keep going
This is lesson 1 of 6 in Idempotency 完全指南:Retry-Safe API 設計實務. Next up:
- HTTP method 的 idempotent 保證
- Idempotency key 的設計與實作
- Stripe API 案例:Idempotency-Key header
- At-least-once delivery 與 exactly-once 的成本
- 常見誤區:idempotent 不代表没有副作用
Wondering turns any topic into short lessons you can read, watch, or listen to, with practice questions and an AI tutor.