HTTP Methods & Idempotency

What is it: HTTP methods (verbs) describe the intended operation. Two key properties: - Safe: the operation does not modify server state. GET, HEAD, OPTIONS are safe. - Idempotent: calling N times has the same effect as calling once. GET, PUT, DELETE, HEAD, OPTIONS are idempotent. POST and PATCH are not.

GET: Retrieve a resource. Safe and idempotent. Response can be cached. Parameters passed in the URL query string (visible in logs, browser history, limited length ~2KB). Never use GET for operations that modify state — browsers, proxies, and crawlers will freely issue GET requests.

POST: Submit data to create a resource or trigger an action. Not safe, not idempotent — submitting the same form twice creates two records. Body carries the payload (no size limit beyond server config). Used when the operation has side effects (place order, send email, initiate payment).

PUT: Replace a resource at the given URL with the provided representation. Idempotent: sending the same PUT twice results in the same state (second write is a no-op). Requires sending the full resource — if you omit a field, it is set to null/default.

PATCH: Partial update — send only the fields to change. More efficient than PUT when updating one field of a large object. Not inherently idempotent: PATCH /counter {increment: 1} called twice increments twice. Can be made idempotent with conditional headers (If-Match: ETag_value).

DELETE: Remove a resource. Idempotent: deleting something already deleted returns 404 but the server state is the same (resource is gone). No body typically.

GET vs POST, summarized: GET: parameters in URL, cacheable, idempotent, bookmarkable, limited size. POST: parameters in body, not cached by default, not idempotent, not bookmarkable, no size limit. Use GET for reads; use POST for writes and complex query payloads. Never use GET to trigger state changes — a Googlebot crawling your links should not accidentally delete data.

Idempotency in practice: Payment APIs use idempotency keys — the client generates a UUID and sends it as a header on the POST. If the network times out and the client retries, the server detects the duplicate key and returns the original response without charging twice.

Common pitfall

Marking an endpoint PUT or DELETE doesn't make it idempotent by itself — idempotency is a property of what the handler's code actually does, and the HTTP method is only a promise about that behavior to callers (browsers, proxies, retry logic) who trust it. A PUT /counters/:id/increment that increments a value on every call is not idempotent no matter what method it uses; calling it "PUT" without the underlying logic actually satisfying "same result no matter how many times it's called" is a contract violation that a retrying HTTP client has no way to detect — it will retry on a timeout, trusting the method's promise, and silently corrupt the counter.