ComparisonHTTP

PUT vs POST

PUT vs POST for REST APIs: idempotency, which one creates vs replaces a resource, and the mistake most APIs make.

Last updated

The short answer

POST creates a new resource and lets the server assign its URL, so calling it twice can create two resources. PUT replaces a resource at a URL the client already knows, and calling it twice with the same body should leave the server in the same state — that's what 'idempotent' buys you.

DimensionPUTPOST
IdempotentYes — repeat calls, same resultNo — repeat calls, more resources
Target URLSpecific resource (/orders/42)Collection (/orders)
SemanticsReplace the resource entirelyCreate a new subordinate resource
Who picks the IDClient already knows itServer usually assigns it
Typical success status200 OK or 204 No Content201 Created
Partial updateNot intended — that's PATCHCommon in practice (loosely)

Choose PUT when

  • →You're updating a resource at a URL the client already owns, like saving a user's profile at /users/42.
  • →You want retries to be free — a dropped connection and a resubmit should never create duplicates.
  • →You're replacing the entire resource representation, not patching one field.

Choose POST when

  • →You're creating a new resource and letting the server assign its ID and URL, like submitting a new order.
  • →The action isn't really a resource update at all — triggering a job, sending an email, processing a payment.
  • →You're sending data that doesn't map cleanly onto REST resource semantics, like a search with a large payload.

The catch nobody mentions

Idempotent doesn't mean 'safe' or 'side-effect free' — a PUT handler that decrements a counter each call, rather than setting an absolute value, breaks the idempotency guarantee even though the verb promises it. Using PUT doesn't make retries safe automatically; your handler has to actually implement replace-with-this-representation semantics for the guarantee to hold.

Common mistakes

  • POST /users/123

    Posting to a specific resource URI usually means you meant to update it, and POST makes no idempotency promise — a retried request can apply the change twice. PUT or PATCH names the intent correctly.

    PUT /users/123
  • PUT /users

    PUT targets a specific resource at a known URI. Putting to a collection asks the server to replace the entire collection, which is almost never intended and which most APIs simply reject.

  • PUT /users/123 with only the changed fields

    PUT replaces the whole resource, so omitted fields should be cleared. Servers that quietly merge instead are behaving like PATCH under a PUT label, which means clients cannot rely on either behaviour.

Questions

What does idempotent actually mean here?

Sending the same request twice has the same effect as sending it once. It does not mean the response is identical — a second PUT may return 200 where the first returned 201 — only that the server ends up in the same state.

When should I use PATCH instead?

When you are sending a partial update. PUT means replace-with-this, so a PUT missing a field should null it. PATCH exists precisely so partial updates do not have to pretend to be full ones.

Can PUT create a resource?

Yes, when the client chooses the identifier — PUT to a URI that does not exist yet is a valid create, returning 201. That is the main case where the choice between the two is genuinely open.

Does any of this matter in practice?

It matters for retries. Proxies, load balancers and client libraries retry idempotent methods automatically and refuse to retry POST, so mislabelling turns a safe retry into a duplicate order.

What status code should each return?

201 with a Location header when something was created, 200 or 204 when it was updated. Returning 200 for everything works and throws away information the client could have used.

Related in Comparisons