Skip to content
API Design Learn/Production REST I: Performance & Reliability
Browsing as a guest. Sign in to save your progress and earn XP as you complete chapters.

HTTP Caching

7 min read

You'll learn to

  • -Use ETag and If-None-Match to let clients avoid re-downloading unchanged resources
  • -Choose appropriate Cache-Control directives for different kinds of resources

HTTP has built-in caching primitives that let a client (or an intermediate cache/CDN) avoid re-fetching a resource that hasn't changed - using them well can eliminate a large fraction of an API's traffic for free, without any application-level caching layer.

ETag: A Fingerprint for the Current State

ETag lets the client ask "has this changed since I last saw it?"
# First request - server returns the resource plus a fingerprint
GET /products/42
HTTP/1.1 200 OK
ETag: "a1b2c3d4"
{"id": 42, "name": "Widget", "price": 19.99}

# Later request - client sends back the fingerprint it has
GET /products/42
If-None-Match: "a1b2c3d4"

# If nothing changed: no body needed, just confirm the cache is still valid
HTTP/1.1 304 Not Modified

# If something changed: full response, with a new ETag
HTTP/1.1 200 OK
ETag: "e5f6a7b8"
{"id": 42, "name": "Widget", "price": 24.99}

A `304 Not Modified` response has no body - the client already has the current representation cached and the server is just confirming it's still valid, saving the bandwidth and processing cost of re-sending unchanged data. The ETag itself is typically a hash of the resource's content or a version number, and it must change whenever the resource's meaningful content changes.

Cache-Control: Who Can Cache This, and for How Long

Different resources want different caching policies
# A public, rarely-changing resource - cache aggressively, even in shared caches
GET /products/42
Cache-Control: public, max-age=3600

# User-specific, sensitive data - never cache in a shared/intermediate cache
GET /users/me/account
Cache-Control: private, no-store

# Content that must always be revalidated before use, even if cached
GET /orders/501/status
Cache-Control: no-cache
  • -`public`: any cache (browser, CDN, proxy) may store this response.
  • -`private`: only the end client may cache it - not a shared/intermediate cache, since the response may be user-specific.
  • -`no-store`: never cache this at all, anywhere - for genuinely sensitive data.
  • -`no-cache`: caching is allowed, but the cache must revalidate with the server (via ETag) before using the cached copy - not the same as `no-store`, despite the confusingly similar name.
  • -`max-age`: how many seconds a cached response can be used without revalidation.

The most common caching mistake is treating every response identically - a product catalog page and a user's private account balance have very different correct caching policies, and applying one blanket `Cache-Control` header across an entire API usually gets at least one of them wrong.

Interview Signal is part of Pro

See a real weak answer next to a real strong one for this exact topic.

Quiz is part of Pro

Test what you just read with a short quiz, and bank the XP.

Ready to Build This?

Design The Cache Architect in the API Design Lab's Production Patterns act.

ScaleDojo Logo
Initializing ScaleDojo