Here’s a strange thing about running a WordPress site: the person least likely to notice it’s slow is you. You visit the same pages all day, your browser has them stashed locally, the server has them warm, and everything snaps into place. Meanwhile a first-time visitor on a phone waits three seconds for the same homepage — and half of them are gone before it finishes painting.
Caching is the set of tricks that closes that gap. It’s the single highest-leverage speed win most WordPress sites are leaving on the table, and it’s also the thing that quietly breaks in the most confusing ways. A site we took over last year was serving a stale homepage that still advertised a sale which had ended three weeks earlier, because a page-cache plugin and a CDN were both holding their own copy and nobody knew which button actually purged it.
This guide walks through what caching really is, the five layers that stack up on a typical WordPress install, and how to reason about them when something goes wrong.
What Caching Actually Is
A cache is a saved copy of expensive work, kept somewhere fast so you don’t redo it. Every time someone loads an uncached WordPress page, PHP boots up, runs your theme and plugins, fires off a dozen or more database queries, assembles the HTML, and hands it back. That whole dance can take hundreds of milliseconds — and it produces the exact same result for the next visitor a second later.
Caching says: do the expensive work once, store the answer, and serve the stored answer to everyone else until it goes stale. The tricky part isn’t storing the copy. It’s knowing when the copy is wrong and needs to be thrown away. That question — cache invalidation — is where nearly every caching headache comes from.
Time to First Byte — how long the server takes to start sending a response — feeds directly into Largest Contentful Paint, one of Google’s Core Web Vitals. Page caching is the most direct lever you have on it, often turning a 600ms server response into 50ms. Faster pages keep visitors around and give you a real ranking edge.
The Five Layers, From the Browser Back to the Database
People say “add caching” like it’s one switch. On a real WordPress stack there are at least five distinct layers, each caching something different, each with its own way to clear it. Understanding which layer holds a stale copy is most of the battle.
1. Browser cache
The visitor’s own browser stores your CSS, JavaScript, fonts, and images on their disk so the next page view doesn’t re-download them. You control this with HTTP response headers — Cache-Control and Expires — that tell the browser how long a file is good for. A logo that changes maybe once a year can safely be cached for months, which is why asset URLs often carry a version string: change the URL and you force a fresh download.
2. CDN / edge cache
A content delivery network like Cloudflare or Bunny keeps copies of your files on servers around the world, so a visitor in Sydney pulls your images from a nearby city instead of your origin server. By default a CDN caches static assets, but most can also do full-page caching at the edge — serving your entire HTML page from their network without ever touching your host. That’s blisteringly fast, and it’s also the layer people most often forget to purge.
3. Page cache
This is what most “caching plugins” mean. The first visitor triggers the full PHP-and-database render, and the finished HTML gets saved — usually as a flat file on disk. Every visitor after that gets the saved file, skipping PHP and MySQL almost entirely. WP Super Cache, W3 Total Cache, WP Rocket, and LiteSpeed Cache all live here. A logged-in user or someone with items in a cart normally bypasses the page cache so they don’t see someone else’s session.
4. Object cache
Object caching works one level deeper, inside WordPress itself. WordPress has a built-in WP_Object_Cache, but out of the box it’s non-persistent — it only remembers things for the duration of a single page load, then forgets everything. Drop a persistent backend like Redis or Memcached behind it and those cached database results survive between requests. This is the layer that helps dynamic, logged-in-heavy sites — WooCommerce stores, membership sites, busy dashboards — where a flat page cache can’t do much.
WordPress knows this matters. Since version 6.1, the Site Health screen will actively suggest adding a persistent object cache once your site does enough database work to benefit from one.
5. Opcode cache (OPcache)
The deepest layer isn’t really WordPress’s at all — it’s PHP’s. OPcache is a PHP extension that compiles your PHP source into bytecode once and keeps that compiled version in shared memory, so PHP doesn’t re-parse the same files on every single request. It’s on by default in modern PHP builds, and any decent host already has it running. You rarely touch it, but it’s worth knowing it’s there.
Browser caches assets on the visitor’s device · CDN caches assets (and optionally full pages) at the edge · Page cache stores finished HTML on your server · Object cache stores database results between requests · OPcache stores compiled PHP bytecode. When something looks stale, work from the visitor’s browser back toward the database until you find the layer still holding the old copy.
Page Cache vs. Object Cache: Which Do You Need?
These two get confused constantly, and they solve different problems. Page caching stores the whole finished HTML page. It’s fantastic for content that looks the same for every anonymous visitor — a blog, a brochure site, a marketing page. If most of your traffic is logged out and reading the same posts, a page cache is the biggest win you can install, and often the only one you need.
Object caching stores the smaller pieces — the results of specific database queries — so WordPress can reuse them without re-querying. It shines exactly where page caching falls down: sites where most requests are personalized and can’t be served from a single frozen HTML file. A WooCommerce checkout, a member dashboard, a forum where everyone’s logged in. There, page caching mostly steps aside, and a Redis-backed object cache is what keeps the database from melting.
Most serious sites end up running both. Page cache handles the anonymous crowd, object cache handles everything dynamic underneath, and they don’t step on each other.
The Real Problem: Cache Invalidation
Storing a copy is easy. Knowing when to throw it away is the hard part, and it’s where the confusing bugs come from. You publish an edit, reload the page, and see the old version — because a cache somewhere is still handing out yesterday’s copy. The frustrating cases are when several layers each hold a stale version and clearing one doesn’t touch the others.
Good caching plugins invalidate automatically: publish or update a post and they purge that page (and related archives) for you. The failure mode is having caches your plugin doesn’t know about. Your page-cache plugin clears its files, but your CDN is still serving full-page HTML from its edge and has no idea you changed anything. That was the stale-sale-banner situation exactly — the WordPress-side cache was clean, and Cloudflare was cheerfully serving three-week-old HTML.
How to clear things, from WP-CLI
When you have terminal access, WP-CLI is the fastest way to flush caches without clicking through admin screens:
wp cache flush— flushes the entire object cache (Redis, Memcached, or the built-in one).wp transient delete --all— clears all transients, WordPress’s own expiring cache stored in the options table (or in your object cache if one’s active).- Most page-cache plugins add their own command too, like
wp rocket cleanorwp w3-total-cache flush all.
If you’ve cleared every WordPress-side cache and still see a stale page, that’s your signal the copy is living outside WordPress — at the CDN or edge — and that’s where you purge next.
Transients: the cache you might already be using
WordPress ships a built-in caching tool many site owners never notice: the Transients API. A transient is a named piece of data with an expiration time — a plugin might cache the result of a slow external API call as a transient for an hour so it isn’t re-fetched on every page load. Without a persistent object cache, transients live in your wp_options database table. With Redis or Memcached in place, they move into fast memory automatically. It’s the same API either way, which is part of why adding an object cache can speed up plugins you didn’t even realize were caching.
A Sane Setup for a Typical Site
You don’t need all five layers tuned to perfection. For most small-business and content sites, a sensible baseline looks like this. Turn on a single page-caching plugin — running two at once is a classic way to create conflicts, so pick one. Put a CDN in front of your assets, and if it offers full-page caching, learn where its purge button is before you turn it on, not after. Make sure your host has OPcache enabled (nearly all do). Add a persistent object cache only if your site is genuinely dynamic or your Site Health screen asks for it — a simple brochure site won’t notice the difference.
The mistake we see most often isn’t too little caching. It’s stacking redundant plugins and half-configured CDNs until nobody can explain why an edit takes twenty minutes to appear. Fewer, well-understood layers beat a pile of overlapping ones every time.
When you’re debugging a “why isn’t my change showing up” problem, test in a private/incognito window. That instantly rules out your own browser cache and any logged-in bypass, so you see what a real anonymous visitor sees — which is usually what the caches are actually serving.
Frequently Asked Questions
Caching is one of those things that’s invisible when it works and maddening when it doesn’t. Map your layers once, learn where each purge button lives, and it stops being a mystery.
Built by amplifi.studio — see also The Slow-Site Tax: How to Fix WordPress Core Web Vitals.