Methods, safety and idempotency

Topics in this section
2 cards

What each method promises

HTTP methods carry promises defined in the HTTP standard (RFC 9110). A method is safe if it only reads: GET and HEAD are safe, so crawlers, caches and prefetchers may call them freely. A method is idempotent if sending the same request twice has the same effect on the server as sending it once: GET, HEAD, PUT and DELETE are idempotent. POST is neither: two identical POSTs to /orders create two orders.

PUT replaces the whole resource with the body you send, so repeating it changes nothing further. PATCH changes part of a resource; it isn't guaranteed to be idempotent ('add 1 to quantity' isn't), though many PATCH requests ('set status to paid') happen to be.

A table of GET, HEAD, PUT, DELETE, POST and PATCH marked safe or idempotent
In real life

A mobile app loses its connection after sending PUT /profile and retries: nothing breaks, the profile ends up the same. If it retries POST /payments the same way, the customer may be charged twice, which is why payments need the idempotency keys from a later lesson.

Check yourself

Which methods are idempotent according to the HTTP standard? (Choose three.)

Select 3, then check.

PUT, PATCH or POST?

Three methods change data, and picking the right one tells clients what is safe to retry.

POST to a collection creates a new item whose id the server chooses: POST /orders → 201 Created, with the new URL in the . PUT to an item URL stores the full representation you send, creating it if the client chose the id: PUT /users/ann/avatar. Fields you leave out are gone, so a PUT must carry the whole resource. PATCH sends only the fields to change: PATCH /orders/42 {"status": "cancelled"}.

DELETE removes an item. Deleting something already deleted leaves the server in the same state; the second call may return 404, and it's still idempotent, because the promise is about the effect, not the status code.

In real life

Changing a user's email: PATCH /users/7 {"email": …}. Replacing a document a user edited in full: PUT /docs/91. Placing an order: POST /orders.

In code: HTTP
POST /orders
{"items": [{"sku": "A1", "qty": 2}]}
→ 201 Created
Location: /orders/42

PATCH /orders/42
{"status": "cancelled"}
→ 200 OK

PUT /users/7/settings
{"theme": "dark", "language": "en"}   # the whole settings object
→ 200 OK
  • The server sets the id on POST; the URL is known in advance on PUT.
  • A PUT without a field removes that field; a PATCH without it leaves it alone.
Check yourself

A client wants to change only the delivery address of order 42 and leave all other fields as they are. Which requests do that? (Choose two.)

Select 2, then check.