Every cache so far has made part of the work cheaper. A query cache saves a query. A shared cache saves a computation. The response still has to be assembled each time.

The leverage and the constraint are the same fact. Because nothing runs on a hit, nothing can adapt to who is asking, and the whole engineering problem of server-side follows from that.
The script is at scripts/labs/serverside/fullpage.py. It runs a real origin that takes 25 milliseconds to render, a real caching reverse proxy in front of it, and 120 real requests each time.

On a hit the application never ran at all. With one personalised span in the page it ran 120 times, and the 4,000 bytes that were identical for every visitor were re-rendered every single time.

A page that is 99 percent identical and 1 percent personal is 0 percent cacheable. That is not a limitation of this proxy, it is how HTTP is defined.

Storing a response marked private is the incident from earlier in this chapter, where one user is served another user's page. Do not look for a way to make the cache store the private page. Look for a way to make the page not private.

A product page, an article, a search result: the content is the same for everybody, and a greeting or a basket count in the corner is not. Every technique that follows is a different way of separating those two boxes.

The first three all work. They differ in who assembles the page, and that decides which team carries the complexity and where it fails.


Both store finished responses and both obey the same headers. If a response is cacheable at the it is cacheable at the proxy, and the reverse is not true, which makes the proxy the right place to start.

Reach for s-maxage before Surrogate-Control. It is standard, widely supported, and covers the common case of a long proxy cache with a short browser cache, which is the split the browser lesson argued for.

This is the same argument as the lesson, one layer up. Most designs use both, with the TTL as the backstop, so the day somebody forgets to purge the damage is bounded rather than permanent.

That is the real reason to put a cache in front of an application. It also means a cache outage delivers twenty times the load to an origin that was never sized for it.


The last branch does not describe a failure. the ingredients is what the application cache, shared cache and query cache lessons were about, and a page that cannot be cached whole is still made much cheaper by caching what it is built from.

Graph the refusal counter next to the hit ratio. A low hit ratio is ambiguous, and a high refusal count tells you immediately that the problem is a response header and not traffic shape or cache size.
4 questions - Score 80% to pass
A page renders in 25 ms. Behind a full-page cache it served 1,580 requests per second. Adding a greeting with the visitor's name changed that to what?
Your proxy cache refuses to store a page. What is the fastest way to find out why?
A proxy cache serving 95 percent of your traffic is restarted for routine maintenance. What should you expect?
A page is technically dynamic and requested 50 times a second. What does one second of full-page caching do?
This is the default worth trying before anything more sophisticated. It requires no edge side includes, no fragment cache and no new component, and it converts the hardest problem in most applications into an ordinary API call.

The session cookie silently costs the most. Many applications create a session for every visitor including anonymous ones, which sets a cookie on every response, which makes the entire site uncacheable at every layer, for visitors who were never logged in.

Normalising the key is the advantage of running your own . You can strip tracking parameters, collapse an Accept-Language header to the three languages you publish, and sort query parameters, and each turns many cache entries back into one.

Micro-caching is the technique teams reject because a page feels too dynamic, without noticing that one second of staleness is shorter than the time a user spends reading the previous screen.
This is the most common way a layer causes an outage, and it happens during routine maintenance and not under unusual load. Test it deliberately: empty the cache under load in staging and see whether the application survives.

The measurement in this lesson used a proxy written in about a hundred lines of Python and still produced 54 times the , because the win comes from not running your application and not from the sophistication of the cache.

Change how the team talks about it. Once the cache is described as load bearing and not as an optimisation, restarting it gets a plan, its capacity gets reviewed, and the cold start gets tested.

This lesson closes the chapter's arc. It began with a cache inside one process, moved outward through shared caches, browsers and CDNs, and ends with the layer that removes the application from the request entirely. Each step gained leverage and lost the ability to know who was asking.