Module 03 · Lesson 03

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.

Intermediate 8 min read Updated 2026-11-01

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

CodeMeaningUse it when
200OKThe request succeeded and the body is the result
201 / 202Created / AcceptedA resource was created, or work was queued for later
204No contentSuccess with nothing to say — a delete, a settings save
301 / 302MovedA link redirects permanently or temporarily
304Not modifiedThe client's cached copy is still good
400 / 422Bad requestThe caller sent something structurally wrong
401 / 403Unauthenticated / ForbiddenNo valid identity, versus a valid identity without permission
404 / 409 / 429Missing / Conflict / Too manyAbsent resource, version conflict, or rate limited
500 / 503Server error / UnavailableYour 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.
  • ETag plus If-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.
Missing Vary is a security bug
If a response depends on the Authorization header and the cache key does not include it, a shared cache can hand one user another user's data. When you mention caching an authenticated endpoint, say the cache key out loud.

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 charge
Instead
Retry on any error, immediately, forever
Do this
Retry only timeouts and 5xx, with jittered exponential backoff and a cap of two or three attempts
Instead
One timeout for the whole request
Do this
A budget per hop, so a slow dependency cannot consume the caller's whole allowance
Instead
Retry inside the deepest service
Do this
Retry as high in the stack as possible; layered retries multiply traffic and can cause a retry storm

Backoff 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

Encrypt in transit
TLS protects bytes on the wire from anyone between client and server, and lets the client verify it is talking to the real host rather than an impostor.
Terminate at the edge
The CDN or load balancer holds the certificate and forwards plaintext inside a trusted network — fewer places to rotate certificates.
Use mTLS between services
Both sides present certificates, so a compromised pod cannot simply call its neighbours. This is the usual substrate for a service mesh.
Rotate and automate
Certificates expire. Automation renewing them before they do is the difference between a calm Tuesday and an outage.

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.

Checkpoint

Answer all 3 questions to finish the lesson.
1. A client sends a payment, times out, and retries. What prevents a double charge?
The key makes the operation addressable, so the retry can be recognised and answered with the original result instead of executing twice.
2. Which response is appropriate when you deliberately reject excess traffic to protect the system?
429 signals rate limiting and tells clients to back off. 500 claims your code broke, 400 blames the caller's format.
3. Which statement about TLS is accurate?
TLS secures the wire and identity of the endpoint. Authorisation, token validation, and at-rest encryption are separate concerns.