Cache Headers: Who Sets, Who Reads
Every cache header has a setter and a reader. Standard headers, Akamai debug headers, and custom headers that do nothing when no rule reads them.
Every cache header has a setter and a reader. If only one side is present, the header does nothing.
I used to look at a header’s name and value only. This time I learned to ask one more question: who reads it?
Standard Headers
| Header | Who sets | Who reads | Example |
|---|---|---|---|
Cache-Control | origin | every cache layer | public, max-age=3600 |
Expires | origin | old-style caches | an absolute time |
Age | every cache layer | next cache layer | age: 54 |
ETag | origin | cache, to compare versions | "32b7140e..." |
If-None-Match | cache, when it refreshes | origin | carries the old ETag |
CDN Own Headers (Akamai as the example, names differ by vendor)
| Header | Purpose |
|---|---|
X-Cache | The result at the edge layer, for example TCP_HIT |
X-Cache-Remote | The result at the second layer (tiered cache) |
Pragma: akamai-x-cache-on | I add it to the request, and then Akamai returns X-Cache and X-Cache-Remote |
Headers We Add Ourselves
| Header | Who adds | Who reads |
|---|---|---|
X-Cache-Bypass: yes | Akamai adds it to every request sent to the origin | Only the LB cache backends that have a written rule |
x-use-proxy: 1 | Akamai adds it to requests with an html, css, or js extension | The load balancer uses it to pick the proxy backend |
The first time I saw X-Cache-Bypass, I thought it was an HTTP standard. It is not. A cache with no rule that reads it simply ignores it. This one sentence is the whole reason behind A Bypass Header Works Only Where a Rule Reads It.
A custom header is not a command. It is only a note. If nobody reads it, it is the same as not written.
Related: One HTTP Request, Cache Freshness: Fresh, Stale, and 304, CDN Terms on One Page, TTL Is Set in Three Places, A Bypass Header Works Only Where a Rule Reads It. Or go back to the series overview.