Caching a whole rendered page turns a 400ms request into a 5ms one. It also means everyone gets the same page - which is exactly right for an article and exactly wrong for a basket, a dashboard or anything that says the visitor's name.
The rule
Cache a response only if it would be identical for a stranger. If any part of it depends on who is asking, either do not cache it, or take that part out of the cached HTML and fetch it separately.
What must never be cached
- Anything behind a login, including the page that shows a login state in the header.
- Basket, checkout, account and order pages.
- Anything with a CSRF token in it - a shared token is not a token. See CSRF and forms.
- Search results with personal history in them.
Tell the cache what varies
# skip the cache when a session cookie is present
fastcgi_cache_bypass $cookie_session $http_authorization;
fastcgi_no_cache $cookie_session $http_authorization;
Prove which one you got
add_header X-Cache-Status $upstream_cache_status;
curl -sSI https://yourdomain.com/ | grep -i x-cache
HIT, MISS and BYPASS in that header answer in one second what an afternoon of reading configuration will not. If a logged-in page says HIT, stop and fix it before doing anything else.
The invalidation half
A cache that is never cleared shows yesterday's price. Purge on publish, and know how to purge everything by hand when a deploy changes the templates.