One header, and the FPM load graph fell off a cliff.

Cache-Control: public, s-maxage=60

A public catalog page on one project renders the same HTML for every anonymous visitor. Same queries, same JSON from the search service, same template, thousands of times per hour. We profiled it, we tuned it, and only then asked the obvious question: why is PHP involved in the second request at all.

HTTP had the answer before my career started. public says a shared cache may store the response. s-maxage gives the CDN or reverse proxy its own lifetime, separate from browser max-age. With Varnish in front, the request path splits in two. MISS: full stack, FPM, database, sixty milliseconds. HIT: the proxy answers from memory, the PHP process never starts, the database never hears about it. Nothing in the application got faster. There was simply less application running.

Invalidation is the famous hard part, so do not start there. Start with a short TTL. Sixty seconds on a page hit ten times per second removes 99.8 percent of the work, and a one minute stale price is acceptable almost everywhere. Purge-on-change can come later, if ever.

The real danger is caching a personalized response. One Set-Cookie, one “Hello, Anna” block, and a shared cache serves Anna’s page to everyone. Anything behind auth is private, full stop. Sessions must not start on public pages: one framework middleware that attaches cookies to everything silently kills all caching, check yours. And read Vary before trusting any of it.

Cache the anonymous majority, run PHP for the logged-in minority. Twenty years old. It beat every optimization I did this year, and I spent months on those.