API Design
Good APIs make retries safe, keep pages stable while data changes, stop clients overwriting each other, and pick a delivery mechanism that matches how data really flows.
Key points
- 1
GET, HEAD, OPTIONS, PUT and DELETE are idempotent; POST and PATCH are not. Make POST safe to retry with an
Idempotency-Keythat the server claims atomically before doing the work and replays afterwards. - 2
Use keyset (cursor) pagination for feeds and exports: sort by a unique key such as
(created_at, id)and ask for rows after the last one seen. Offset pagination duplicates or skips rows when data changes, and it slows down on deep pages. - 3
Prevent lost updates with ETags:
If-Matchon writes,412 Precondition Failedwhen the version is stale, and428 Precondition Requiredwhen the header is missing. - 4
Long jobs return
202 Acceptedplus a status resource the client polls (or a webhook when done), rather than holding a connection open for minutes. - 5
SSE for one-way server pushes over HTTP, WebSockets for chatty two-way traffic, webhooks for server-to-server notification, and long polling as the proxy-friendly fallback.
- 6
In GraphQL, fix N+1 resolvers with a per-request DataLoader that batches keys within one tick and memoises results for that request only.
Common traps
Storing an idempotency key only after the side effect leaves a race: concurrent retries both miss the key and both charge.
A retried conditional PUT can get 412 because of its own first attempt. Re-read the resource before reporting a conflict.
Webhook signatures cover the raw bytes. Verifying against re-serialised JSON fails or covers the wrong content.
Read the source
Test yourself on API Design
Ten questions, with the answer and explanation after each one.