Recommended Free Tools
An idempotent API makes repeated attempts at the same logical operation converge on the same intended server-side effect. That matters when a client times out and cannot tell whether a request committed, or when a queue delivers work again. The key distinction: idempotency can make retries safe for a defined operation, but it does not guarantee exactly-once delivery across an entire distributed system.
What is idempotency?
RFC 9110, the IETF’s HTTP Semantics specification, defines idempotence by the intended effect on the server: “A request method is considered ‘idempotent’ if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.” The relevant definition and retry guidance appear in section 9.2.2.
| # | Preview | Product | Price | |
|---|---|---|---|---|
| 1 |
|
API Design Patterns | $59.99 | Buy on Amazon |
| 2 |
|
The Design of Web APIs, Second Edition | $50.14 | Buy on Amazon |
| 3 |
|
Patterns for API Design: Simplifying Integration with Loosely Coupled Message Exchanges... | $51.52 | Buy on Amazon |
| 4 |
|
API Design for C++ | $89.24 | Buy on Amazon |
| 5 |
|
Designing Web APIs: Building APIs That Developers Love | $25.49 | Buy on Amazon |
As an Amazon Associate I earn from qualifying purchases.
That definition is about the intended effect, not about every internal event. A server may log every attempt, for example, even if all attempts leave the business record in the same final state. Nor does idempotency promise that a request is delivered only once. It gives a system a way to handle repeated attempts without repeating the operation’s intended effect.
Why retries can create duplicate effects
Consider a client that submits an order. The server saves it, but the response is lost before the client receives it. From the client’s perspective, a timeout does not reveal whether the server never received the request, is still processing it, or committed the order and lost only the response. Sending the request again may create a second order unless the API can recognize it as a retry of the first logical operation.
#1 Best Overall
- API Design Patterns
- ABIS BOOK
- Manning Publications
The same uncertainty can arise when a connection drops, a process restarts, or an upstream queue redelivers work. A retry policy alone cannot resolve the ambiguity: the client needs to reuse an identity for the operation, and the server needs durable state that lets it recognize and safely handle that identity.
HTTP method semantics versus idempotency keys
HTTP defines some methods as idempotent by semantics. RFC 9110 identifies safe methods, PUT, and DELETE as idempotent. That does not mean every implementation is automatically correct: an application still has to preserve the method’s intended repeat-safe effect. For example, repeating a DELETE may return a different response after the resource is gone while still leaving the server in the same intended state.
POST and PATCH are not idempotent by default in Google Cloud’s HTTP API guidance. For a mutating operation that may be retried, an API can define an application-level idempotency key so attempts with the same key represent the same logical action.
| Approach | What makes repetition safe | Where it fits |
|---|---|---|
| HTTP method semantics | The method’s defined intended effect is unchanged by repeating the request. | Methods defined as idempotent, including safe methods, PUT, and DELETE under RFC 9110. |
| Application-level key | The API recognizes a stable key for one logical operation and applies its documented duplicate-handling contract. | Mutations such as a POST that may be retried after an uncertain outcome. |
RFC 9110 says, “A proxy MUST NOT automatically retry a request with a non-idempotent method.” It allows an exception when the proxy knows the operation’s semantics are idempotent or can determine the original request was never applied. For application developers, the practical lesson is to make retry safety explicit rather than assume that a transport or client can infer whether a mutation already happened.
Rank #2
How idempotency keys work
An idempotency key is a stable identifier for one user intent, such as creating a particular order or provisioning a particular resource. The client generates it once and reuses it for retries of that operation. A genuinely new operation gets a new key. Generating a fresh key for every transport attempt defeats deduplication because the server sees each attempt as a different operation.
A robust contract usually specifies all of the following:
- Scope: Which account, tenant, endpoint, or operation the key applies to.
- Request matching: Whether the same key must be accompanied by the same parameters, and what happens if it is not.
- Concurrency: What a second request does while the first is still running.
- Outcome handling: Whether the API replays a saved response, returns an operation reference, or reports that work is still in progress.
- Failure behavior: Which failures are stored as the outcome and which allow the client to retry execution.
- Retention: How long the key and outcome remain available, and what happens after they expire.
These choices are part of the API contract, not universal properties of idempotency keys. Clients need to know them to retry safely; server teams need to implement them consistently.
Free tools Windows power users keep installed
One-click scans. No signup required.
Designing server-side duplicate handling
1. Define what counts as the same operation
Start with the user intent, not the individual network request. Decide which attempts should collapse into one operation and which represent new work. A payment attempt, order creation, and resource provisioning request may each need a stable identity that survives retries but changes when the user deliberately starts a new operation.
Rank #3
2. Claim the key atomically
When a request arrives, the server needs to check and claim the key in a way that remains correct if two copies arrive at nearly the same time. A cache lookup followed by a separate write is not enough: both requests could observe no record and then both execute the mutation. Use an atomic claim or an equivalent transaction or uniqueness constraint, scoped to the relevant account and operation.
Store a request fingerprint or equivalent information alongside the key so that a client cannot silently reuse the same key with different input. The API should define how it compares requests and what response it returns for a mismatch; provider contracts differ on this behavior.
3. Coordinate the key record with the business effect
Persisting a key separately from the business mutation can leave a dangerous gap. If the mutation commits but the key record does not, a retry may execute the operation again. Where possible, write the operation state and business effect in the same database transaction. When work must continue in another service or system, use an outbox or workflow pattern so downstream effects have their own durable coordination.
This is a design approach, not a single architecture required by HTTP or by all providers. The necessary implementation depends on where the business effect occurs and what must survive a restart.
Rank #4
4. Represent in-progress work explicitly
Concurrent duplicates can arrive while the original request is still executing. Choose whether the duplicate waits, receives an in-progress response, or gets a retryable conflict. Whatever the response, the server must prevent the second request from independently executing the same mutation. For asynchronous operations, returning an operation reference and letting the client check its status can be more useful than pretending that the work has already finished.
5. Save enough outcome state to honor the contract
Once an operation reaches the point defined by the API contract, persist the information needed for a retry: that may be a response status and body, an operation reference, or both, along with metadata that distinguishes in-progress from terminal work. A duplicate should communicate the result of the original logical operation rather than rerun the mutation.
What provider contracts show in practice
Provider behavior illustrates why an idempotency key’s details must be documented rather than assumed. Stripe’s API reference, checked on October 7, 2026, describes keys for POST requests. It says Stripe stores the first status code and response body after endpoint execution begins, then returns that saved result on later uses of the same key, including when the saved result is a 500 response. Stripe compares parameters and errors if the same key is reused with different parameters.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Stripe also documents exceptions to saving a result: validation failures and concurrent-request conflicts where endpoint execution has not begun do not produce a saved idempotent result. Its reference says keys may be removed once they are at least 24 hours old; after pruning, reuse can result in a new request. That is Stripe’s contract, not a general retention rule for APIs. Provider behavior can change, so teams implementing against a vendor should verify its live documentation.
Best Value
Amazon Pay likewise documents its own key behavior and advises against using its idempotency header for GET, PATCH, and DELETE, which its guidance treats as idempotent by definition. That instruction belongs to Amazon Pay’s API contract; it should not be generalized to every API or header.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Retention, replay, and asynchronous work
Retention determines how long the server can recognize a retry. Set the horizon from realistic client retries, queue redeliveries, and recovery windows, then document it. Once a key expires or is pruned, an old request may be treated as new. Retention is therefore part of correctness, not just a storage setting.
For a synchronous operation, the API may replay the original outcome for a duplicate. For asynchronous work, the first request may have created an operation that is still running, so the duplicate may need to receive an in-progress state or the same operation reference. In either case, the API should explain what a client can safely do next.
Idempotency also has boundaries. If an operation triggers a payment processor, sends a message, or calls another service, protecting only the local database does not automatically prevent duplicate downstream effects. Each boundary needs its own coordination, such as a downstream idempotency mechanism or durable workflow state. The overall design can make repeated attempts safe for the defined operation without claiming exactly-once transport across services.
Failure cases to test
Tests should exercise the points where a client or server can lose certainty, rather than only the successful first request. Include cases such as:
- The server commits the business mutation, but the response is lost; the client retries with the same key.
- Two requests with the same key arrive simultaneously.
- The server restarts while an operation is in progress, then receives a retry.
- The key store is unavailable when a mutation request arrives.
- The same key is reused with a changed request body or parameters.
- A retry arrives after the documented retention horizon.
- A downstream side effect is redelivered after the local operation has already been recorded.
For each case, verify the observable business effect, the response or operation state, and whether the client can determine what to do next. In particular, define what happens when the key store is unavailable: silently proceeding without deduplication may turn a transient infrastructure failure into duplicate business work.
Practical implementation checklist
- Define the logical operation and the conditions that make two attempts the same user intent.
- Have the client create a sufficiently unique key once, then reuse it for every retry of that operation. Stripe recommends a high-entropy value such as a UUID for its own API and sets its own key-length limit; neither is a universal API requirement.
- On receipt, validate the request and atomically claim or find the key within the appropriate account, tenant, and operation scope.
- Compare the request against the saved fingerprint or equivalent, and apply the documented mismatch behavior.
- Coordinate the key state with the business mutation and downstream work so a restart or redelivery cannot repeat the effect.
- Define how concurrent duplicates are answered and what state a client sees while the original operation is running.
- Persist the outcome or operation reference needed to handle later retries without re-running the mutation.
- Set a retention period that covers expected retry and redelivery windows, and document what happens after expiration.
- Exercise response-loss, concurrency, restart, mismatch, expiry, and downstream-redelivery cases in tests.
These steps describe a design pattern, not a particular header name or database requirement. The right details are those that make the contract atomic, durable, and understandable to both callers and maintainers.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




