← Bank
Conceptual

Idempotency in HTTP

ConceptualJunior~4m
httprestapi-design

Prompt

A client hits your API to charge a card, the response times out, and the client retries the exact same request. Walk me through how HTTP's notion of idempotency decides whether that retry is safe — and which methods give you that guarantee for free.

How this round runs

This is a conversation that escalates — I'll keep asking "and what happens when…" to find the edge of what you know. A calibrated "I'm not certain, but reasoning from the spec…" beats a confident wrong answer, and I'm listening for whether you can connect the property to a real consequence, not just recite a table.

Model answer

I'll frame it around the property first, then the per-method consequences. Idempotency means N identical requests leave the server in the same state as one — the resulting state is invariant, not necessarily the response body. That's the whole reason it matters: networks lose responses, so a client often can't tell "succeeded" from "never arrived." If the method is idempotent, retrying is safe; if it isn't, a blind retry can double-charge or create a duplicate.

Going a layer down to why each method lands where it does: GET, HEAD, OPTIONS are idempotent because they're also safe — they mutate nothing, so repetition is trivially invariant. PUT and DELETE are idempotent but not safe: a PUT /users/123 with a full representation overwrites to the same target value every time, and a second DELETE /users/123 leaves the resource just as gone as the first (the status may differ — 204 then 404 — but the state is identical, which is what the property is actually about).

POST is the odd one out: it's defined as non-idempotent because its conventional meaning is "create a subordinate resource," and two POST /orders calls create two orders. That's exactly the case where a timeout-and-retry is dangerous. The honest boundary for me: the spec defines this at the semantic level — the server implementation can break the guarantee (a non-idempotent PUT) or add one where the verb doesn't (an idempotent POST), so the method only tells you the intended contract, not what a given endpoint actually does.

Signals — what a strong answer shows
  • Framed idempotency as state-invariance, distinct from a fixed response body, before listing methods
  • Separated safe from idempotent (DELETE is idempotent but not safe) instead of conflating them
  • Tied the property to the concrete consequence: a lost response makes retries safe only when idempotent
  • Reasoned about WHY each verb's semantics put it where it is, not just memorized the table
  • Flagged that the method states intent, not what the endpoint's implementation actually guarantees
Follow-ups — where it goes next
  • Is POST ever idempotent? → idempotency keys: client sends a unique key, server dedupes on it and replays the stored response on retry
  • And what happens when two retries race with the same idempotency key concurrently? → the key needs a uniqueness constraint / atomic insert, not just a read-then-write check
  • DELETE returns 404 on the second call — does that violate idempotency? → no, the property is about state, not the status code