Ctrl + K
HTTP20 min read

Idempotent HTTP Requests

Understand HTTP idempotency, how repeated requests behave, which methods are idempotent, and how idempotency keys make APIs safer to retry.

Published: 2026-10-05

Idempotency is one of the most important concepts when designing reliable HTTP APIs. It describes what happens when the same request is performed more than once and is especially important when a client cannot determine whether an earlier request succeeded.

Network failures can happen after a server has processed a request but before the client receives the response. If the client retries the request, the server may receive the same operation twice. Whether that is safe depends partly on the idempotency characteristics of the operation.

GET and PUT are defined as idempotent HTTP methods, while POST and PATCH are not inherently idempotent. However, idempotency can also be implemented at the application level, for example by using idempotency keys for operations such as payment creation or order submission.

What Does Idempotent Mean?

An HTTP method is idempotent when making the same request multiple times has the same intended effect on the server as making it once.

PUT /api/users/42
Content-Type: application/json

{
  "name": "Alex",
  "role": "developer"
}

If this exact PUT request is sent once or several times, the intended final state of the user should be the same: the user has the specified name and role.

Idempotency does not mean that every response must be identical. Response headers, timestamps, logging information, metrics, or other incidental effects can differ between requests. The important property is the intended effect on the resource or server state.

A Simple Example

Suppose an API allows a client's name to be changed with PUT:

PUT /api/users/42
Content-Type: application/json

{
  "name": "Alex"
}

Sending the request once changes the name to Alex. Sending the same request again still leaves the name as Alex.

The second request does not mean that the name should become something different. It asks the server to establish the same intended state again.

Idempotency Does Not Mean Read-Only

A common misunderstanding is that idempotent requests cannot modify data. That is incorrect. An idempotent operation can change server state; the important property is that repeating the same operation does not produce additional intended changes after the first successful application.

OperationIdempotent?Why
Set user status to activeYesRepeating it keeps the status active
Replace a resource with a representationYesRepeating it establishes the same representation
Delete a resourceYesAfter the first deletion, repeating the request does not create another deletion effect on the resource
Create a new orderUsually noRepeating it can create another order
Increment a counterNoEvery repetition changes the counter again

Idempotency vs Safety

Idempotency and safety are different HTTP concepts. A safe method is intended for operations that do not request a state change. An idempotent method may change state while still having idempotent semantics.

PropertyMeaning
SafeThe method is intended to be read-only with respect to the requested resource state
IdempotentRepeating the same request has the same intended effect as performing it once

GET is both safe and idempotent. PUT is idempotent but not safe because it can modify a resource. DELETE is also idempotent even though it changes server state.

Which HTTP Methods Are Idempotent?

MethodIdempotentSafe
GETYesYes
HEADYesYes
OPTIONSYesYes
PUTYesNo
DELETEYesNo
POSTNoNo
PATCHNot inherentlyNo

The table describes the HTTP method semantics. An individual application can also design a particular endpoint to behave idempotently even when the HTTP method itself is not defined as idempotent.

GET Is Idempotent

GET is defined as a safe and idempotent method. It is intended to retrieve a representation of a resource rather than request a state-changing operation.

GET /api/products/123

Sending this request once or multiple times should have the same intended effect on the resource: no requested modification is made.

The server can still record logs, update metrics, perform authentication checks, or perform other internal work. Those incidental effects do not change the method's HTTP semantics.

PUT Is Idempotent

PUT is idempotent because its semantics are based on creating or replacing the target resource representation at a known URI.

PUT /api/users/42
Content-Type: application/json

{
  "name": "Alex",
  "email": "[email protected]"
}

Repeating the same request should establish the same intended state rather than creating a new user each time.

DELETE Is Idempotent

DELETE is also defined as idempotent. Consider:

DELETE /api/users/42

The first request may remove the user. Repeating the request does not remove another copy of that user because the resource has already been removed.

The responses can differ. The first request might return 204 No Content, while a subsequent request might return 404 Not Found. Different responses do not automatically make the operation non-idempotent.

POST Is Not Inherently Idempotent

POST is not defined as an idempotent HTTP method. This is particularly important for resource creation.

POST /api/orders
Content-Type: application/json

{
  "productId": 123,
  "quantity": 1
}

If the request creates an order, sending the same request twice can create two orders. That is an additional intended effect, so the operation is not naturally idempotent.

PATCH Is Not Inherently Idempotent

PATCH is used for partial modifications, but the HTTP method itself does not guarantee idempotency.

A PATCH operation that sets a value can be idempotent:

PATCH /api/users/42
Content-Type: application/json

{
  "status": "active"
}

Repeatedly setting the status to active produces the same intended state.

An operation that increments a value is different:

{
  "operation": "increment",
  "amount": 10
}

If every request increases a balance by 10, repeating the same request produces another change. That operation is not idempotent.

Idempotency and Retries

One of the most important reasons to understand idempotency is request retries. Networks are unreliable, and a client can lose the response even when the server successfully processed the request.

Imagine that a client sends a request to create an order. The server creates the order and sends a response, but the connection fails before the client receives it.

Client → POST request → Server
Client ← response     ← Server

          connection fails

Client: "Did the request succeed?"

The client cannot necessarily distinguish between these two situations:

  • The request never reached the server.
  • The server received and processed the request, but the response was lost.

If the client simply sends the POST again, it could accidentally create a second order.

Why Retrying PUT Is Easier

Suppose a client uses PUT to establish a user's profile:

PUT /api/users/42
Content-Type: application/json

{
  "name": "Alex",
  "role": "developer"
}

If the client does not receive the response, repeating the same PUT request should establish the same intended resource state. This makes retries easier to reason about.

Why POST Needs More Care

A POST operation that creates a new resource can produce a new result each time it is submitted. Therefore, a client should not automatically assume that an unknown outcome means it is safe to repeat the request.

For operations where duplicate processing would be harmful, the API can provide an application-level mechanism such as an idempotency key.

What Is an Idempotency Key?

An idempotency key is a unique value generated by the client and sent with a request. The server uses the key to recognize repeated attempts belonging to the same logical operation.

POST /api/payments
Content-Type: application/json
Idempotency-Key: 7f2d9b3e-8c12-4e6a-example

{
  "amount": 4999,
  "currency": "USD",
  "orderId": "order-123"
}

If the client does not receive a response, it can retry the request with the same idempotency key. The server can recognize that the retry represents the same logical operation rather than a new operation.

How Idempotency Keys Work

  • The client generates a unique key for a logical operation.
  • The client sends the key with the request.
  • The server stores or otherwise tracks the key and the operation's result.
  • If the same key is received again, the server can recognize the duplicate attempt.
  • The server returns the previously established result or applies the API's documented duplicate-request behavior.

The exact implementation is application-specific. An idempotency key is not automatically provided by HTTP itself; it is an API-level convention.

Idempotency Key vs Request ID

An idempotency key should not be confused with a request ID used for tracing or logging.

ConceptPurpose
Idempotency keyAllows the server to recognize repeated attempts of the same logical operation
Request IDHelps identify and trace an individual request through logs and services

A system can use both. A request ID can change for each network attempt, while the same idempotency key can be reused when those attempts represent one logical operation.

Idempotency Keys and Payments

Payments are a common example because duplicate processing can have serious consequences. A client might submit a payment and then lose the connection before receiving confirmation.

POST /api/payments
Idempotency-Key: payment-attempt-8f42

{
  "amount": 2500,
  "currency": "USD"
}

If the client retries with the same key, the payment service can distinguish the retry from an entirely new payment request, provided the service implements idempotency keys according to its documented contract.

⚠️ Never assume that a POST endpoint is safely retryable just because it accepts an idempotency key. Check how the specific API defines key lifetime, duplicate requests, payload mismatches, failures, and response replay behavior.

The Idempotency Key Must Be Reused for Retries

If a client generates a completely new idempotency key for every retry, the server may interpret every attempt as a new operation.

First attempt:
Idempotency-Key: abc123

Retry:
Idempotency-Key: abc123

The same key associates both network attempts with the same logical operation.

Idempotency Keys Should Represent One Operation

A client should generally generate a new key for a genuinely new operation. Reusing an old key for an unrelated operation can cause the server to treat the new request as a duplicate.

SituationIdempotency key
First attempt at creating an orderGenerate a new key
Retry because response was lostReuse the same key
User intentionally creates another orderGenerate a new key
Retry after a documented transient failureUsually reuse the same key when the API supports it

Server-Side Storage of Idempotency Keys

A server needs a way to recognize previously processed keys. Depending on the architecture, the information can be stored in a database, distributed cache, or another durable or coordinated storage system.

A simplistic implementation might associate the key with the request parameters and the resulting response.

{
  "key": "payment-attempt-8f42",
  "requestHash": "example-hash",
  "status": "completed",
  "responseStatus": 201
}

Production systems need to consider concurrency, expiration, storage failures, multiple application instances, and what happens if two requests with the same key arrive at nearly the same time.

Concurrency and Idempotency

Two identical requests can arrive concurrently rather than sequentially. A server must therefore prevent both requests from independently performing the operation before either one has recorded the idempotency key.

This often requires atomic operations, unique database constraints, distributed locking, or another concurrency-control mechanism appropriate for the system.

Idempotency and Databases

Database constraints can help enforce idempotent application behavior. For example, an order table can contain a unique idempotency key associated with the operation.

CREATE UNIQUE INDEX idx_orders_idempotency_key
ON orders (idempotency_key);

A unique constraint can prevent multiple rows from being created with the same key. The application still needs to define how duplicate requests are handled and how the original result is returned.

Idempotency Is Not the Same as Exactly-Once Delivery

Idempotency is sometimes confused with exactly-once delivery. They are related but different concepts.

A network can deliver the same request more than once. An idempotent operation makes repeated processing safe with respect to its intended state. It does not mean that the network delivered the message exactly once.

This distinction is especially important in distributed systems, where messages can be duplicated, delayed, retried, or delivered after a timeout.

Idempotency and At-Least-Once Processing

Many distributed systems prefer at-least-once delivery because it is safer to retry a message than to risk losing it. The trade-off is that consumers may receive duplicates.

Making the processing operation idempotent allows the system to tolerate those duplicate deliveries.

Idempotent vs Non-Idempotent Operations

OperationTypical behavior
Set account status to suspendedIdempotent
Replace user profileIdempotent
Delete a specific resourceIdempotent
Create a new resource with a server-generated IDUsually non-idempotent
Increment a counterNon-idempotent
Append an event to a listUsually non-idempotent

Making an API Operation Idempotent

An API operation can often be designed to be idempotent even when its HTTP method does not inherently guarantee idempotency.

  • Define a stable identifier for the logical operation.
  • Accept an idempotency key when duplicate processing is possible.
  • Store enough information to recognize repeated attempts.
  • Make duplicate processing return a consistent logical result.
  • Use database constraints where appropriate.
  • Handle concurrent requests using atomic operations.
  • Define how long idempotency keys remain valid.
  • Document what happens when the same key is reused with different request data.

Idempotency and Request Payloads

A robust API should define what happens if the same idempotency key is reused with a different payload.

First request:
Idempotency-Key: abc123

{
  "amount": 100
}

Later request:
Idempotency-Key: abc123

{
  "amount": 500
}

Treating these as the same operation would be dangerous because the payloads conflict. APIs commonly reject such reuse or otherwise define explicit behavior.

Idempotency and HTTP Status Codes

An idempotent operation can return different HTTP status codes on repeated requests. What matters is the intended effect rather than requiring the exact same status code every time.

First request:
DELETE /api/users/42

HTTP/1.1 204 No Content

Repeated request:
DELETE /api/users/42

HTTP/1.1 404 Not Found

The different responses do not change the fact that DELETE is defined as idempotent. After the first successful deletion, repeating the deletion does not create another deletion effect on the resource.

Retries Should Not Be Blind

Idempotency makes retries easier to reason about, but it does not mean every failed request should automatically be retried.

  • Determine whether the method and endpoint are safe to retry.
  • Consider whether the server might already have processed the request.
  • Use an idempotency key for supported non-idempotent operations.
  • Respect server rate limits and retry-related response headers when applicable.
  • Use bounded retries rather than retrying indefinitely.
  • Apply backoff between repeated attempts when appropriate.
  • Avoid retrying permanent client errors such as invalid request data.

Exponential Backoff

When an operation is appropriate for retrying, clients often use exponential backoff. Instead of immediately sending another request after every failure, the client waits for progressively longer intervals.

Attempt 1 → wait
Attempt 2 → wait longer
Attempt 3 → wait longer again
Attempt 4 → stop after the configured retry limit

Random jitter is often added to backoff intervals so that many clients recovering from the same failure do not retry simultaneously.

Idempotency in Frontend Applications

Frontend applications can encounter the same uncertainty as backend clients. A user might click a button, the browser sends a request, and the connection temporarily fails before the frontend receives the response.

For operations such as creating an order, submitting a payment, or registering a resource, the frontend and backend need a clear strategy for duplicate requests.

The frontend should not attempt to solve server-side idempotency by simply disabling a button. UI protection can reduce accidental duplicate clicks, but it cannot protect against network retries, browser refreshes, multiple clients, or requests that reach the server more than once.

Idempotency in REST APIs

REST APIs benefit from meaningful HTTP semantics. GET can retrieve resources, PUT can establish a representation at a known URI, DELETE can remove a resource, and POST can submit data for processing or create a resource in a collection.

Following these semantics makes API behavior easier for clients to understand. When a custom operation needs stronger retry guarantees, an API can document an application-level idempotency mechanism.

Idempotency in GraphQL

GraphQL does not use HTTP methods in exactly the same way as a REST API. Queries are generally read operations, while mutations represent operations that can change application state.

GraphQL mutations are not automatically idempotent simply because the request is sent to a single endpoint. If a mutation can be retried, its schema and server implementation need to define how duplicate operations are handled.

mutation CreateOrder($input: CreateOrderInput!) {
  createOrder(input: $input) {
    id
    status
  }
}

An application can include an idempotency key in the mutation input when the API is designed to support it.

Testing Idempotent APIs

Testing idempotency means checking what happens when the same logical operation is submitted more than once. A request builder or API testing tool can be used to send repeated requests and inspect the resulting status codes and response bodies.

  • Send the original request.
  • Record the response and resulting resource state.
  • Send the same request again.
  • Compare the resulting resource state.
  • For idempotency-key APIs, repeat the request with the same key.
  • Try concurrent duplicate requests when the operation is sensitive to race conditions.
  • Test reuse of an idempotency key with a different payload if the API supports idempotency keys.

Example Test Scenario

POST /api/orders
Content-Type: application/json
Idempotency-Key: order-attempt-123

{
  "productId": 42,
  "quantity": 1
}

Send this request twice with the same key. The expected result depends on the API contract, but a properly designed idempotency mechanism should prevent the retry from unintentionally creating a second logical order.

Common Idempotency Mistakes

Mistake 1: Assuming Every Request Is Idempotent

Not every HTTP operation can safely be repeated. Treating POST or an arbitrary PATCH operation as automatically retryable can result in duplicate records or repeated side effects.

Mistake 2: Confusing Different Responses With Non-Idempotency

An idempotent operation can return different responses on repeated requests. Idempotency concerns the intended effect on server state, not whether the response body and status code are identical.

Mistake 3: Generating a New Key for Every Retry

If an API uses idempotency keys, generating a new key for each retry defeats the purpose because the server cannot associate the attempts with the same logical operation.

Mistake 4: Storing Only the Key

A production idempotency implementation usually needs more context than a key alone. It may need to associate the key with the request, operation status, result, expiration information, and other metadata.

Mistake 5: Ignoring Concurrent Requests

Two requests with the same key can arrive at nearly the same time. If both requests check for the key before either one records it, both could process the operation. Idempotency logic therefore needs appropriate concurrency control.

Idempotency Checklist

  • Know whether the HTTP method is inherently idempotent.
  • Do not assume PATCH operations are idempotent.
  • Treat non-idempotent POST operations carefully when retries are possible.
  • Use idempotency keys for supported operations that need duplicate protection.
  • Reuse the same key when retrying the same logical operation.
  • Generate a new key for a genuinely new operation.
  • Define key expiration and duplicate-request behavior.
  • Protect against concurrent requests with the same key.
  • Validate that the same key is not reused with incompatible request data.
  • Test duplicate and retry scenarios explicitly.

Frequently Asked Questions

What is an idempotent HTTP request?

An idempotent HTTP request is one where making the same request multiple times has the same intended effect on server state as making it once. The responses do not have to be identical.

Which HTTP methods are idempotent?

GET, HEAD, OPTIONS, PUT, and DELETE are defined as idempotent HTTP methods. POST is not inherently idempotent, and PATCH is not inherently idempotent.

Is POST idempotent?

POST is not inherently idempotent. Repeating a POST can create multiple resources or trigger an operation multiple times. An API can, however, add application-level idempotency using mechanisms such as idempotency keys.

Is PATCH idempotent?

PATCH is not inherently idempotent. A specific PATCH operation can be idempotent if repeating it produces the same intended state, but other PATCH operations, such as increments or appends, may not be.

Why is DELETE idempotent?

DELETE is idempotent because repeating the request does not create another deletion effect on the same resource after it has already been deleted. A later request can still return a different status such as 404.

What is an idempotency key?

An idempotency key is a unique client-generated value associated with one logical operation. The server uses it to recognize retries or duplicate submissions and prevent them from being processed as separate operations.

Can an idempotent request return different responses?

Yes. Idempotency concerns the intended effect on server state, not identical responses. For example, the first DELETE request might return 204 while a repeated request might return 404.

Why does idempotency matter for payments and orders?

Network failures can occur after a payment or order has been processed but before the client receives the response. Without duplicate protection, retrying the request could perform the operation again. Idempotency keys can allow the server to recognize the retry as the same logical operation.

Conclusion

Idempotency means that repeating the same request has the same intended effect on server state as performing it once. GET, PUT, and DELETE are defined as idempotent HTTP methods, while POST and PATCH are not inherently idempotent.

The concept becomes especially important when network failures make the result of a request uncertain. Idempotent operations are easier to retry safely, while sensitive non-idempotent operations may require application-level mechanisms such as idempotency keys.

Reliable APIs should define their retry behavior explicitly, protect important operations against duplicate processing, handle concurrent requests correctly, and document how idempotency keys work. For frontend and backend developers, understanding idempotency is essential for building APIs that behave predictably when requests are repeated.

Found an issue?

Found an error, outdated information, or something missing from this article? Let me know through the Contact page.

Your feedback helps improve our articles and keep them accurate and useful.