HTTP that behaves well, and TLS that is not an afterthought
Caching headers, timeouts, retries, and encryption: the unglamorous parts that decide whether a system stays up.
What you will be able to do
- Use status codes and cache headers deliberately rather than decoratively
- Make retries safe with idempotency keys
- Describe what TLS protects and what it does not
- Explain connection reuse, keep-alive, and where timeouts belong
Status codes are part of the design
| Code | Meaning | Use it when |
|---|---|---|
| 200 | OK | The request succeeded and the body is the result |
| 201 / 202 | Created / Accepted | A resource was created, or work was queued for later |
| 204 | No content | Success with nothing to say — a delete, a settings save |
| 301 / 302 | Moved | A link redirects permanently or temporarily |
| 304 | Not modified | The client's cached copy is still good |
| 400 / 422 | Bad request | The caller sent something structurally wrong |
| 401 / 403 | Unauthenticated / Forbidden | No valid identity, versus a valid identity without permission |
| 404 / 409 / 429 | Missing / Conflict / Too many | Absent resource, version conflict, or rate limited |
| 500 / 503 | Server error / Unavailable | Your bug, or you are shedding load deliberately |
The two that carry design weight are 429 and 503. Returning them means you built a system that protects itself, and you can point at it when someone asks what happens during a spike. A URL shortener redirect answers 301 for a link that never changes, which lets browsers and CDNs cache the redirect and takes load off your servers entirely.
Caching is a header negotiation
Cache-Control: public, max-age=31536000, immutable— for fingerprinted assets that never change.Cache-Control: private, max-age=60— small per-user responses that are fine a minute stale.Cache-Control: no-store— anything with credentials, balances, or personal data.ETagplusIf-None-Match— the server answers 304 with no body, saving bandwidth on unchanged JSON.Vary: Accept-Encoding, Authorization— prevents one user's cached response being served to another.
Idempotency: retries without duplicates
Networks fail in the middle of writes. If a client sends a payment, times out, and retries, the naive backend charges twice. The fix: the client generates a unique key per logical operation, the server stores it alongside the result, and a repeat of the same key returns the original response instead of re-executing.
POST /payments
Idempotency-Key: 8f14e45f-ea5b-4c1a-9d2e-3f1b7c92a001
First call -> executes, stores {key: result}, returns 201
Retry -> finds key, returns the stored result, no second chargeBackoff without jitter is a scheduled traffic wave: every client retries at the same moment. Add randomness and the herd spreads out.
TLS in one page
What TLS does not do: it does not check permissions, does not protect a stolen database backup, and does not stop a legitimate user from calling your API with bad intentions. Authentication and authorisation are separate layers, and the combination of TLS plus short-lived tokens is what actually closes the loop.
Worth remembering
- Cache-Control decides who caches and for how long; ETag plus 304 avoids resending unchanged bodies.
- A retry without an idempotency key turns one failed write into two records.
- TLS protects data in transit and proves server identity — it does not authorise the caller or protect data at rest.
- Every network call needs a timeout, and the retry budget must be smaller than the total request budget.