QuestionsNetworking/Security

Safe and idempotent methods: GET vs POST

HTTP SemanticsEasyNetworking/Security

What do 'safe' and 'idempotent' mean for HTTP methods, and why do these properties matter in practice?

What it tests

Understanding method semantics that browsers, caches, and retry logic depend on — not just 'GET reads, POST writes'.

Approach & answer

Two properties define how a method is allowed to behave. SAFE means the request has no side effects on the server — it only reads. GET, HEAD, and OPTIONS are safe. IDEMPOTENT means making the request N times has the SAME effect on server state as making it once. GET, HEAD, PUT, and DELETE are idempotent; POST and PATCH are generally NOT. Note safe implies idempotent (reading twice changes nothing), but idempotent does not imply safe (DELETE changes state, but deleting twice leaves the same 'gone' state as deleting once). Why these matter beyond trivia: (1) CACHING — safe methods (GET) can be cached by browsers, CDNs, and proxies because they don't change anything; POST responses generally aren't cached. Putting a state-changing action behind GET is a real bug: a prefetcher, a crawler, a browser preloader, or a cache can fire it unexpectedly (the classic 'a search-engine bot deleted our records by following GET /delete?id=5 links'). (2) RETRIES — clients, proxies, and load balancers safely RETRY idempotent requests after a network hiccup because a duplicate is harmless; they must NOT blindly retry a non-idempotent POST, or you get double charges / double orders. This is exactly why 'submit payment' is a POST and why real systems add an IDEMPOTENCY KEY so even a POST can be safely retried without duplicating the effect. (3) Browser behavior — refreshing or navigating back to a POST prompts 'resubmit form?' precisely because POST isn't idempotent. So the practical rules: use GET only for reads (never for actions), use POST for non-idempotent creates/actions, use PUT/DELETE when the operation genuinely is idempotent, and design write endpoints so retries don't double-apply. Choosing the method by its semantics — not just 'GET vs POST' by habit — is what lets the whole caching/retry infrastructure around your app behave correctly.

Use this technique when

Choosing a method for an endpoint; deciding what a client may retry; avoiding action-behind-GET bugs.

Code

Method   Safe?  Idempotent?   Notes
-------  -----  -----------   ---------------------------------
GET      yes    yes           cacheable; reads only
HEAD     yes    yes           GET without a body
PUT      no     yes           full replace; retry-safe
DELETE   no     yes           deleting twice == deleted once
PATCH    no     no*           partial update
POST     no     no            create/action; NOT retry-safe

Consequences:
  * caches/prefetchers may fire GET -> never hide an action behind GET
  * proxies/clients retry idempotent methods -> POST needs an idempotency key
  * browser "resubmit form?" prompt exists because POST isn't idempotent

References