“Just add caching” is advice that hides four different layers. They store different things, live in different places, and fail in different ways — which is why misconfigurations are so common and so confusing. This guide separates them for good.
Layer 1: Browser cache
The visitor’s own disk stores static assets (images, CSS, JS) with expiry headers. Cost: zero. Scope: repeat visits only. You control it via cache headers (hosting config or plugin). It never goes stale for the visitor who clears it — and it is the reason “I fixed it but still see the old version” happens.
Layer 2: Page cache (the big lever)
The rendered HTML of a page is stored and served without running PHP or querying MySQL. This is where TTFB drops from 600ms to double digits — the numbers in our cache plugin comparison all come from this layer.
- What it stores: full HTML per URL.
- Invalidation: on content updates (good plugins hook this automatically).
- The trap: role-varied and personalized content — wholesale pricing, member areas, cart fragments. Naive page caching serves the first visitor’s version to everyone, the leak pattern documented in the pricing comparison.
- Where it lives: plugin (file-based), or server-level (nginx FastCGI, LiteSpeed) which is faster still.
Layer 3: Object cache
Stores database query results in memory (Redis/Memcached). It helps what page caching cannot: uncached visits, logged-in users, admin screens. The setup and verification steps are in the Redis guide. Invalidation: automatic on writes — this layer is smart about freshness, which is why it complements rather than competes with page cache.
Layer 4: CDN cache
Edge servers worldwide store static assets (and optionally pages) close to visitors. Gains depend on geography: modest for local audiences, dramatic for international ones — the honest measurement in the CDN comparison. Invalidation: TTL-based, plus purge APIs.
How the layers stack
A returning visitor’s request flows: browser cache → CDN edge → page cache → object cache → MySQL. Each layer that answers saves the deeper ones from working. They are configured to stack, not to fight: one page-cache layer only (plugin OR server, never both), object cache alongside, CDN at the edge.
The misconfigurations we find most
- Two page caches stacked — stale content roulette, impossible to debug from the outside.
- Page cache caching everything — member content leaking, carts behaving oddly, wrong-language pages on multilingual sites (see the translation comparison).
- No cache invalidation on updates — editors publish and readers see the old page for hours.
- Browser cache too aggressive — CSS changes invisible to returning visitors for weeks.
The configuration that works
One page-cache layer with correct exclusions, Redis object cache if the host provides it, CDN for static assets, sensible browser-cache TTLs (short for CSS/JS during redesigns). Measure the result the honest way — cached and uncached — per the CWV guide. The free audit identifies which of the four layers your site currently runs — and which it fights.
Four: browser cache (visitor's disk), page cache (rendered HTML), object cache (query results in Redis/Memcached), and CDN cache (edge servers). Each stores different data and invalidates differently. No — one page-cache layer only. Stacked page caches cause stale-content roulette that is nearly impossible to debug from outside the server. No — page caches bypass logged-in visitors by design. That is the object cache's job: Redis speeds up the database work for every request, cached or not. Cache invalidation failed somewhere in the chain: the page cache, CDN, or over-aggressive browser-cache headers. Good cache plugins purge on publish; CDNs need a purge call or short TTLs.What are the layers of caching in WordPress?
Can I use two cache plugins at once?
Does page caching fix logged-in users?
Why do visitors still see old content after I publish?