API Design

Idempotency in APIs Explained

Learn what idempotency means in API design, why retries create duplicate actions, and how idempotency keys protect backend workflows.

Quick answer

An API operation is idempotent when making the same request multiple times has the same effect as making it once. Idempotency matters because clients retry requests after timeouts, connection resets, process crashes, and unclear responses.

Without idempotency, a retry can create duplicate orders, duplicate payments, duplicate emails, duplicate background jobs, or repeated state transitions that users did not intend.

What idempotency means

Idempotency is about the effect of an operation, not whether the server does zero work. A repeated request may still be authenticated, logged, checked, or read from storage. The important part is that the business result does not happen twice.

For example, retrying a successful create-payment request should not charge the customer twice. The server should either return the original result or tell the client that the request conflicts with an existing operation.

HTTP method examples

Some HTTP methods are expected to be idempotent by design, while others are not.

MethodUsually idempotent?Why
GETYesIt should read data without changing server state.
PUTYesReplacing a resource with the same representation has the same final state.
PATCHDependsA patch can be idempotent, but it depends on the operation semantics.
DELETEUsually yesDeleting an already deleted resource should not create another side effect.
POSTUsually noCreating something twice can create two resources or two side effects.

The method alone is not enough. Your API contract and backend implementation must make the behavior true.

Why retries create risk

Consider a checkout request:

POST /api/orders

The server creates the order, but the client times out before receiving the response. The client does not know whether the order was created. If it retries the same POST and the server treats it as a brand-new request, the user may get two orders.

Distributed systems make this common. Networks fail, load balancers close connections, workers restart, queues redeliver messages, and clients retry after transient errors. Idempotency turns those retries into a controlled workflow.

Idempotency keys

An idempotency key is a client-generated unique value sent with a request. The server stores the result for that key and returns the same result if the same request is retried.

A common header shape is:

Idempotency-Key: 7b3f6b6d-1f8d-48d5-9c5a-2a6f7f4d6c52

The key should be unique for one logical operation. A random UUID v4 is a common starting point; use the UUID Generator when you need test keys for examples or local debugging. Reusing the same key for a different payload should be rejected because it can hide a client bug.

A typical request flow

A practical backend flow looks like this:

  1. Receive a request with an idempotency key.
  2. Validate the key format and scope it to the authenticated user or account.
  3. Create a unique record for the key before performing the side effect.
  4. If the key already exists, compare the stored request fingerprint.
  5. Return the stored response when the fingerprint matches.
  6. Reject the request when the same key is reused with a different payload.
  7. Store the final response after the operation completes.

The unique insert matters. If two identical requests arrive at the same time, a check-then-insert sequence can still race. Let the database or durable store enforce uniqueness.

What to store

Store enough data to make retries deterministic:

FieldPurpose
keyThe client-generated idempotency key.
scopeUser, account, tenant, or endpoint scope for the key.
requestHashFingerprint of the request method, path, and normalized body.
statusprocessing, succeeded, or failed.
responseStatusHTTP status code to return for matching retries.
responseBodyResponse body to return for matching retries.
expiresAtCleanup time so the store does not grow forever.

The exact shape depends on the risk level. Payments and provisioning workflows need stronger guarantees than a simple newsletter signup form.

Status codes for idempotency

Status code choices should be consistent with the rest of the API:

ScenarioPossible status code
First request succeeds and creates a resource201 Created
Matching retry returns stored resultSame status as the first completed request
Same key reused with different payload409 Conflict or 422 Unprocessable Entity
Request is still processing202 Accepted or 409 Conflict, depending on contract
Missing required key for a protected endpoint400 Bad Request

Read REST API Status Codes Explained for broader status code tradeoffs, or use the HTTP Status Code Lookup when you need a quick reference while designing retry behavior.

Backend implementation notes

Scope keys by actor and operation. A key used by one account should not collide with the same key used by another account. A key used for POST /orders should not accidentally affect POST /payments.

Use a durable store with a uniqueness guarantee. A relational table with a unique constraint is a common starting point. Cloudflare D1, Postgres, MySQL, or another transactional database can work if the insert and update flow is designed carefully.

Set an expiration policy. Many systems keep idempotency records for 24 hours, 7 days, or another business-appropriate window. The retention period should be longer than the client retry window.

Common mistakes

The first mistake is generating the idempotency key on the server after the request arrives. The client must send the same key again on retry, so the client needs to own the key.

The second mistake is storing only the key and not the request fingerprint. If a client accidentally reuses a key with a different payload, the server may return the wrong stored response.

The third mistake is relying on an in-memory map. That may work in local testing, but it breaks across process restarts, multiple instances, and distributed deployments.

The fourth mistake is making the side effect before the idempotency record is reserved. Under concurrency, two workers can both decide the key is new and perform the action twice.

When idempotency is worth adding

Add idempotency to operations where duplicate side effects are expensive or user-visible:

  • Payments and refunds.
  • Order creation and checkout.
  • Account provisioning.
  • Email or notification sending.
  • Background job creation.
  • Webhook processing.
  • External API calls that may be retried.

Not every endpoint needs idempotency keys. For low-risk operations, simpler validation and duplicate detection may be enough.

Read REST vs RPC for API style context and REST API Status Codes Explained for response patterns around retries and conflicts. Use the HTTP Status Code Lookup for quick 409, 422, 429, and 5xx guidance, the UUID Generator for local idempotency key examples, and the Unix Timestamp Converter when comparing retry windows, expiration times, and log timestamps. You can also browse the API Design topic cluster for related backend API articles.