Requests, TLS, and cache

Read and control cache behavior

Use cache status, cache keys, response directives, and purge operations without treating every response as safely cacheable.

Caching answers repeated requests near your users and saves work at the origin. It is only correct when the cache key separates every response variant that matters. Two users must never share a cached response that was personal to one of them.

Read the status before changing anything

Every proxied response carries a CF-Cache-Status header. Request a static asset twice:

curl -sI https://flaviocopes.com/img/og.png | grep -i cf-cache-status
# cf-cache-status: MISS
curl -sI https://flaviocopes.com/img/og.png | grep -i cf-cache-status
# cf-cache-status: HIT

MISS means Cloudflare fetched from the origin and stored a copy. HIT means the edge answered without touching the origin.

You will also meet DYNAMIC. It means Cloudflare did not consider the response cacheable. HTML gets this by default, because Cloudflare caches by file extension unless you add Cache Rules.

Next to the status, read Cache-Control (what the origin asked for), Age (how long the copy has been stored), and validators like ETag. They tell you what the current behavior is. Change configuration only after you can explain what you see.

What must never share a key

Never cache personalized or authorization-dependent responses under a shared key. A cached /account page is a data leak with a CDN in front of it.

If a response depends on a cookie or an Authorization header, keep it out of the shared cache, or make the differing input part of the key.

Prefer versioned URLs over purging

Purging is a repair tool, not a substitute for correct freshness rules. If you rename an asset on every release, old and new versions coexist and nothing needs purging:

/assets/app.3f9c1a.css   cached forever, safe
/assets/app.css          needs purging on every deploy

The versioned name changes when the content changes, so a long max-age becomes harmless. Reach for a purge when something wrong was cached, not as a routine deploy step.

Try this: request one versioned asset twice and explain both cache statuses. Then change its URL and confirm the new URL starts at MISS. That is the behavior a global purge only approximates.

Lesson completed