Skip to content

Idempotency & Safety

Two properties decide whether a request can be safely repeated. They are easy to mix up, so let’s pin them down precisely.

  • Safe — the request has no observable effect on server state; it only reads. GET, HEAD, and OPTIONS are safe.
  • Idempotent — making the request N times leaves the server in the same state as making it once. GET, HEAD, OPTIONS, PUT, and DELETE are idempotent. POST and (in general) PATCH are not.

Every safe method is idempotent, but not every idempotent method is safe — DELETE changes state yet is idempotent.

flowchart TD
  M{Method} --> GET[GET / HEAD: safe + idempotent]
  M --> PUTDEL[PUT / DELETE: idempotent, not safe]
  M --> POST[POST: neither]
  M --> PATCH[PATCH: usually neither]
Where each method sits on the safe/idempotent grid

Networks drop responses. When a client (or proxy, or load balancer) does not hear back, it may retry. If the method is idempotent, retrying is harmless. If it is not — like a POST that charges a card — a blind retry could charge twice.

JavaScript

When you genuinely need a non-idempotent create to tolerate retries, use an idempotency key: the client sends a unique Idempotency-Key header, and the server remembers the result for that key so a repeat returns the original outcome instead of acting twice. We cover the mechanics in Versioning & Caching.

Which statement is true?
Why is retrying a non-idempotent POST risky?
What lets a non-idempotent create tolerate retries safely?