Idempotency in HTTP and APIs: What It Means

An idempotent operation produces the same result no matter how many times it is repeated.

Idempotency

Idempotency is a concept that sounds technical but has a very practical effect: it defines whether repeating a request produces the same outcome as running it once. It is essential for building APIs that are safe to retry, that handle network failures gracefully, and that clients can depend on without fear of unintended side effects.

What Does Idempotent Mean

An operation is idempotent if performing it multiple times produces the same result as performing it once. The word originates in mathematics, where a function is idempotent if applying it to its own output does not change the result. The number one is idempotent under multiplication because multiplying it by itself any number of times always returns one.

In HTTP and API design, idempotency answers a specific practical question: if a request is retried due to a network failure, a timeout, or an ambiguous response, will the retry cause any additional side effects beyond the first successful execution? If the answer is no, the operation is idempotent and safe to retry automatically.

It is important to note that idempotency is about the end state, not the response code. A DELETE request to remove a resource returns 200 or 204 on the first call when the resource exists. On a retry after the resource has already been deleted, it returns 404. The response differs, but the end state is identical on both calls: the resource does not exist. The operation is still idempotent.

Idempotency of HTTP Methods

MethodIdempotent?Safe?Why
GETYesYesOnly retrieves data and produces no side effects. Repeating it returns the same data without changing anything.
HEADYesYesIdentical to GET but returns only headers with no body. No side effects regardless of how many times it is called.
OPTIONSYesYesReturns the allowed methods and CORS permissions for a URL without modifying anything on the server.
PUTYesNoReplaces a resource completely with the provided data. Sending the same PUT twice results in the resource being in the same state as after the first call.
DELETEYesNoDeletes the resource. Retrying after a successful delete returns 404, but the end state is the same: the resource no longer exists.
POSTNoNoCreates a new resource on each call. Sending the same POST request twice typically creates two separate records with different IDs.
PATCHDependsNoSetting a specific value such as an email address is idempotent. Incrementing a counter by one is not, because each call changes the value further.

Safe vs Idempotent: The Difference

Safe and idempotent are related but distinct properties. A method can be one, both, or neither. Understanding the difference helps you reason about what can go wrong when requests are repeated or cached.

  • Safe means the method does not change server state at all. It is purely read-only. GET, HEAD, and OPTIONS are safe. You can call them freely without any concern about side effects because they only retrieve information.
  • Idempotent means the method can be repeated without producing additional effects beyond the first call. DELETE is idempotent but not safe. It changes server state by removing a resource, but it changes it in the same way every time. The resource is gone after the first call, and all subsequent calls find the same absent resource.
  • Neither applies to POST in the typical case. A POST request both modifies server state and produces different outcomes when repeated, because each call creates a new record. This is why retry logic for POST requires special handling.
PropertyWhat It MeansMethods
SafeDoes not modify server state. Read-only operations.GET, HEAD, OPTIONS
Idempotent but not safeModifies server state but produces the same end result on repeated calls.PUT, DELETE
Neither safe nor idempotentModifies state and produces different results on repeated calls.POST, and some PATCH operations

Why Idempotency Matters in Practice

Networks are unreliable. Requests time out, connections are dropped, and clients often cannot tell whether a request was received and processed or whether it was lost entirely. When this ambiguity occurs, the client must decide whether to retry. Idempotency determines whether that retry is safe.

For idempotent methods, automatic retries are always safe. HTTP clients, load balancers, and infrastructure tools routinely retry GET, PUT, and DELETE requests on failure without any risk of unintended consequences. For non-idempotent methods like POST, a retry can cause serious problems.

  • Retrying a POST to a payment endpoint could charge the user twice for the same transaction
  • Retrying a POST to a form submission endpoint could create duplicate database records or send duplicate emails
  • Retrying a POST to create an order could result in two shipments being dispatched
  • Retrying a PUT to update a resource is always safe because the resource ends up in the same state
  • Retrying a DELETE is always safe because the resource is absent regardless of whether the first or the tenth call actually removed it

Idempotency Keys for POST Requests

For operations where POST is the correct method but duplication is completely unacceptable, such as payment processing or order creation, APIs use a pattern called idempotency keys. The client generates a unique identifier for each logical operation and includes it as a request header. The server stores the result of the first successful execution associated with that key. On any subsequent request with the same key, the server returns the stored result without re-executing the operation.

POST with an idempotency key:
POST /api/payments HTTP/1.1
Idempotency-Key: a7f3c2d9-1234-4abc-8def-000000000001
Content-Type: application/json

{"amount": 5000, "currency": "USD", "recipient": "user_42"}

The key is typically a UUID generated by the client before the request is sent. If the first request times out and the client cannot tell whether it was processed, it resends the same request with the same key. If the server processed the original request, it returns the stored result. If it did not, it processes the request now and stores the result for future duplicates. The client receives the correct outcome either way with no duplication.

Major payment and communication APIs implement this pattern. Stripe requires idempotency keys on all POST requests that create or modify objects. PayPal uses a similar PayPal-Request-Id header. Twilio uses an X-Twilio-IdempotencyKey header for message sending. The pattern is also applicable to any internal API where POST operations must be protected against duplicate execution.

Designing Idempotent APIs

Building idempotency into your API from the start makes it significantly more robust in distributed environments. A few design principles help achieve this.

  • Use PUT when the client controls the resource ID: If the client assigns the ID of the resource being created or updated, use PUT instead of POST. A PUT to /api/users/42 with a full user object is idempotent because the same request always results in the same resource state at that URL.
  • Prefer absolute values over relative changes in PATCH: A PATCH that sets status: "active" is idempotent. A PATCH that sets increment_count: true is not. Where possible, design PATCH operations to set absolute values rather than apply relative modifications.
  • Support idempotency keys on critical POST endpoints: For any POST operation where duplicate execution would cause real harm, accept and honour an idempotency key header. Store results indexed by key and deduplicate on the server side.
  • Return consistent responses on duplicate requests: When a duplicate is detected via an idempotency key, return the same response as the original successful call, including the same status code and body. This allows clients to treat the retry transparently as if it were the first call.

Frequently Asked Questions

  1. Is deleting a resource that does not exist idempotent?
    Yes. The first DELETE call on an existing resource removes it and returns 204. A subsequent DELETE call on the now-absent resource returns 404. The response code differs between the two calls, but the end state is identical on both: the resource does not exist. Idempotency is about the state of the system after the operation, not the response code, so DELETE is considered idempotent regardless of whether the resource was present when the call was made.
  2. Is PATCH idempotent?
    It depends entirely on the operation being performed. A PATCH that sets a specific field to a specific value, such as updating an email address to a new string, is idempotent because repeating it leaves the resource in the same state. A PATCH that performs a relative modification, such as incrementing a view counter or appending an item to a list, is not idempotent because each call produces a different result. When designing PATCH operations, prefer absolute value assignments over relative modifications wherever possible to make the endpoint safe to retry.
  3. Should I always prefer PUT over POST for resource creation?
    Use PUT when the client is responsible for generating the resource identifier, for example creating a resource at a specific UUID the client controls. In this case PUT is idempotent and safe to retry. Use POST when the server is responsible for assigning the identifier, which is the more common pattern for typical CRUD APIs. POST is the appropriate choice for creation in REST conventions when the server generates the ID, but you should implement idempotency keys for any POST endpoints where duplication would cause harm.
  4. How long should a server store idempotency key results?
    There is no universal standard, but most implementations store results for between 24 hours and 7 days. The retention period should be long enough to cover any realistic retry window for the client, including delayed retries caused by prolonged network outages or queue processing. Stripe stores idempotency keys for 24 hours. After the retention period expires, a request with the same key is treated as a new operation. Document your retention period clearly in your API documentation so clients can design their retry logic accordingly.
  5. Does idempotency guarantee the same response code on every call?
    No. Idempotency guarantees the same end state of the resource or system, not the same HTTP response code. A DELETE that returns 204 on the first call and 404 on subsequent calls is still idempotent. A PUT that returns 201 Created when the resource does not yet exist and 200 OK when it does is still idempotent. When using idempotency keys on POST endpoints, many implementations do return the same response code and body for duplicate requests as a convenience for clients, but this is a design choice rather than a requirement of idempotency itself.

Conclusion

Idempotency is a core API design property that makes distributed systems safer, more reliable, and easier to reason about. GET, PUT, and DELETE are idempotent by the nature of what they do. POST is not, but idempotency keys provide the same safety guarantee for POST endpoints where duplicate execution is unacceptable. Understanding safe and idempotent properties, designing your PATCH operations carefully, and implementing idempotency keys on critical endpoints makes your API resilient against the network failures and ambiguous timeouts that are an unavoidable reality of distributed computing. See also HTTP methods, REST API design, and HTTP status codes.