Requests

Safe and idempotent methods

Understand the guarantees behind safe and idempotent methods so retries, links, caches, and automated clients behave predictably.

Not all HTTP methods behave the same when a client sends them more than once. Two words cover most of the difference: safe and idempotent.

A safe method should only read data. It must not change server state. GET, HEAD, and OPTIONS are safe. You can open a link, prefetch a page, or let a crawler walk your site without worrying that a safe request will create an order or delete a row.

An idempotent method has the same intended effect whether you send it once or five times.

PUT is idempotent. Replacing /notes/42 with the same JSON twice leaves the resource in the same final state.

DELETE is idempotent too. The first call removes the note. Later calls might return 404, but they do not delete a second resource.

POST is usually not idempotent. Submitting a checkout form twice can create two charges. That is why payment APIs often require an idempotency key header: the server recognizes duplicates and responds with the original result instead of running the action again.

This matters the moment a connection drops. Mobile networks and load balancers retry idempotent requests all the time. If your GET /account endpoint accidentally writes a log entry that charges a fee, retries hurt you.

You can see idempotence in a toy API. Imagine DELETE /notes/99 returns 204 No Content the first time. A repeat call might return 404 Not Found because the note is already gone. Different status codes, same outcome: no note left with id 99.

My advice: keep reads on safe methods, make updates idempotent where you can, and treat POST as “may have side effects” in docs and client code.

Try this on your own project: pick one write endpoint and ask what happens if the client retries after a timeout. If the answer is “duplicate rows,” add idempotency or switch to an idempotent method where the semantics fit.

Lesson completed