Engineering · 2 min read
Symptom: HTML, CSS, and JS Keep Going to Origin
Same domain, same TTL, but HTML left the CDN edge 17 times more often than images. Splitting the numbers by route ruled out every suspect but one.
The domain and the TTL were the same. But HTML left the edge 17 times more often than images.
This is the starting point of the whole chase.
- In August, the HTML offload was only 84%. It jumped between 59% and 97% each day.
- In other words, out of every 100 HTML requests, 16 went back to our server.
First I Compared Files on the Same Domain with the Same TTL
| File | Route | Requests per file | Leaves the edge |
|---|---|---|---|
| Type 1 (shared script) | bucket | Very high | 0.5% |
| Type 2 (image) | bucket | Medium | 2.1% |
| Type 3 (style file) | proxy | Medium | 15.4% |
| Type 4 (HTML) | proxy | Medium | 36.1% |
| Type 5 (asset script) | proxy | Medium | 41.3% |
- The data came from the live CDN log, a sample of 11 minutes.
- “Leaves the edge” means time to first byte ≥ 50 ms. The report also counts a refresh hit as a hit (CDN Terms on One Page).
- Type 2 and Type 5 have a similar request volume and the same TTL. But Type 5 left the edge about 20 times more often.
- Only one difference was left: which route the file takes (How the Load Balancer Picks a Backend).
Three Suspects I Ruled Out
- Query string: the cache key keeps only one parameter. The script that loads the HTML also sends no query string.
- Upload interface: the interface only uploads folders and saves records. The browser fetches the HTML only when the page shows.
- An HTML-only rule: the property has only one cache rule for all file types (Akamai Property: One Edge Config).
At first nobody doubted the scripts, because the overall numbers looked healthy. The reason is that Type 1 made up most of the script traffic, and it takes the bucket route. When I split the numbers, Type 5 was as bad as HTML.
An average hides the problem. Split down to the route, and the answer shows up.
Related: CDN Terms on One Page, How the Load Balancer Picks a Backend, A Bypass Header Works Only Where a Rule Reads It. Or go back to the series overview.