Skip to content
All writing
Engineering · 8 min read

From One Interview Line to a Cache Loop

HTML left the CDN edge 17 times more often than images on one domain. This series chases why, from one HTTP request to a cache loop behind the load balancer.

Map of the CDN cache series: the path of one request through Akamai, the load balancer, and two LB cache routes, plus the refresh loop on the proxy route

I thought a CDN was one box. After I chased this problem, I learned it is a chain.

The Story

I knew CDNs only at the level of a system design interview: “Add a CDN layer and users load faster.”

Later I looked at a CDN report and found something strange. The domain and the TTL were the same. But HTML left the edge 17 times more often than images. I dug in and found a whole route where files often do not stay in the cache. This route matches by file extension: html, css, and js. Large HTML files were the worst.

To find the cause, I started from “what is a request” and dug down. This series follows the order in which I learned. Each post is one piece I added during the chase.

A Few Terms First

The whole series uses one analogy: a chain of stores with one central warehouse and many local shops.

TermPlain meaningAnalogy
RequestA browser asks a server for a fileA customer asks the shop for one item
HeaderA small label on a request or responseThe notes field on an order
OriginThe server where the file really livesThe central warehouse
CacheKeep a copy and reuse it next timeStock on the local shop shelf
Edge serverA server near the user that holds copiesThe shop near your home
CDNA network of many edge serversThe whole chain of shops
Load balancerThe entrance to the origin. It sends each request to a different machine behind itThe dispatcher at the warehouse door
ProxyA program in the middle that fetches a file and passes it onAn errand runner who goes to the warehouse for you
Bypass headerA label that tells the cache “do not use your copy”A note that says “please get fresh stock from the warehouse”

A customer asks the nearby shop. The shop goes to the warehouse only when it has no stock. Here is the problem in this story: there is a hidden small shelf at the warehouse door. And it cannot read the notes.

Road Map

Question: "Why is the cache hit rate for HTML so much worse than for images?" 1 Basics01020304 2 Terms and headers0506 3 Akamai0708 4 The design I assumed09101112 5 The chase1314151617 6 What I learned18
One question splits into six phases and 18 posts, read in order from basics to the lesson.

Why It Happens: Three Conditions Cross

The LB cache on the proxy route does not read the bypass header ×The LB cache serves the stale copy first after expiry(stale-while-revalidate) ×The proxy returns 405 to a HEAD refresh =The copy is always expired,so Akamai keeps each copy fresh for only 1 second
Each condition is small alone, but together they leave every copy expired at Akamai.
  1. A bypass header works only where a rule reads it: the LB cache on the bucket route steps aside. The one on the proxy route does not (A Bypass Header Works Only Where a Rule Reads It).
  2. The old copy still moves forward: after expiry, the LB cache serves the old file first. The copy reaches Akamai with a very large Age (Stale-While-Revalidate: Serve Old First, Refresh in the Background).
  3. The refresh always fails: the LB cache refreshes with HEAD, and the proxy accepts only GET (The Proxy Rejects HEAD, So the Refresh Always Fails).

Each of the three conditions is small on its own. Together, every request for a large HTML file goes back to the origin (Five Parts Make One Loop).

What I Learned

Now I follow one request along the whole path. At each layer I ask three questions. Is there a cache here? Which headers does it read? Can a purge reach it? (What I Learned: A Cache Is a Chain, Not a Box)

A CDN makes things faster. But to know where a request stops, you must walk the layers one by one.

Sources: ByteByteGo: How does CDN work, RFC 9111: HTTP Caching, RFC 5861: stale-while-revalidate

↑↓ navigate ↵ open esc close