apyhub
Cover illustration for What Is an Idempotent Request?
ApyHub

What Is an Idempotent Request?

What Is an Idempotent Request?

An idempotent request produces the same result whether it runs once or ten times.

Setting a user's name to "Ada" is idempotent. Do it five times and the name is Ada. Charging a card 20 GBP is not idempotent. Do it five times and you have charged 100 GBP.

The reason this matters is retries. A network failure leaves you unsure whether the request arrived. If it was idempotent, retry safely. If it was not, retrying may double-apply it.

01Which Methods Are Idempotent

RFC 9110 is explicit. PUT, DELETE, and the safe methods (GET, HEAD, OPTIONS, TRACE) are idempotent. POST and PATCH are not.

MethodSafeIdempotentWhy
GETYesYesReads nothing changes
HEADYesYesSame as GET without the body
OPTIONSYesYesAsks what is allowed
PUTNoYesSets the resource to a given state
DELETENoYesDeleting twice leaves it deleted
POSTNoNoCreates something new each time
PATCHNoNot necessarilyDepends on the operation

Safe and idempotent are different. Safe means the request does not change anything. Idempotent means repeating it does not change anything further. Every safe method is idempotent; the reverse is not true, since PUT and DELETE change things but do so repeatably.

DELETE is the one that confuses people. The first DELETE returns 204 and the second returns 404, which look like different results. Idempotency is about the state of the server, not the response code. After one DELETE the resource is gone. After five it is still gone. That is idempotent.

02Why Retries Depend On It

RFC 9110 says a client SHOULD NOT automatically retry a non-idempotent request unless it knows the semantics are safe or can detect the original never applied. It also says a proxy MUST NOT automatically retry non-idempotent requests.

The dangerous case is a timeout. Your request may have arrived and succeeded, with the response lost on the way back. You cannot tell the difference between that and a request that never landed.

Retry an idempotent request and the worst case is a wasted call. Retry a non-idempotent one and you may have created two orders.

03Making POST Idempotent

You often need POST to be retry-safe anyway. The standard answer is an idempotency key.

The client generates a unique key, usually a UUID, and sends it with the request:

http

POST /payments HTTP/1.1 Idempotency-Key: 6f1a2c4e-9d3b-4a71-8f22-0e5b7c1d9a44 Content-Type: application/json {"amount": 2000, "currency": "GBP"}

The server stores the key with the result. If the same key arrives again, it returns the stored response instead of processing the request a second time.

Four rules that make this work:

  1. The client generates the key, not the server. The point is that a retry reuses the same one.
  2. One key per logical operation, not per attempt. A retry must send the same key.
  3. Store the response, not just the key. The retry should get the original result back.
  4. Expire keys after a sensible window. Twenty-four hours is common.

04Where It Goes Wrong

Generating a new key on retry. Defeats the entire mechanism. The key must be created when the operation is created, and reused on every attempt.

Assuming PATCH is idempotent. Setting a field is. Incrementing a counter is not. Check the operation rather than the method.

Retrying immediately. Even for idempotent requests, retry with exponential backoff. Immediate retries against a struggling server make things worse.

Ignoring it in queues and workers. Most job queues offer at-least-once delivery, meaning your handler will occasionally run twice. Idempotency is not only an HTTP concern.

05FAQ

What does idempotent mean?

An operation is idempotent when performing it several times has the same effect on the server as performing it once. Setting a value is idempotent; adding to it is not.

Which HTTP methods are idempotent?

GET, HEAD, OPTIONS, TRACE, PUT and DELETE. POST is not. PATCH depends on what the patch does.

Is DELETE idempotent if the second call returns 404?

Yes. Idempotency is about server state, not the status code. After one DELETE the resource is gone and further DELETEs leave it gone, which is the same state.

What is the difference between safe and idempotent?

Safe means the request does not modify anything at all. Idempotent means repeating it causes no further change. GET is both. PUT is idempotent but not safe, because it does modify the resource.

How do I make a POST request idempotent?

Send a client-generated idempotency key, usually a UUID, in a header. The server stores the key with its response and returns the stored result if the same key arrives again rather than processing it twice.

Should I retry a failed POST?

Not automatically, unless it carries an idempotency key or you can verify the original never applied. A timeout does not tell you whether the request succeeded, and retrying blindly can duplicate the effect.

Is PATCH idempotent?

It depends. A patch that sets a field to a value is idempotent. One that increments a counter or appends to a list is not. Design yours to be idempotent where possible.

06Related

Source: RFC 9110, section 9.2.2

07About ApyHub

ApyHub is a curated API catalog for developers, teams and AI agents: file conversion, data validation, OCR and extraction and more across 20 categories. One key covers all of it, every endpoint is MCP-ready so AI agents can discover and call them directly, and every service page has a playground for testing before you build.

EU-based and EU-hosted, which keeps data residency simple for teams with GDPR obligations.

Browse the catalog | Get a free API key - no credit card required.