Muhammad Basim
Pin for WordPress Caching Explained: The Four Layers
WordPress

WordPress Caching Explained: The Four Layers

Muhammad Basim
Muhammad Basim
·12 min read

Part of the comprehensive guide on: Speed Up WordPress: What Actually Moves the Number

WordPress Caching Explained: The Four Layers

There are four caching layers on a WordPress site, they cache different things, and stacking two of the same kind causes bugs rather than speed.

Layer What it stores Who usually provides it
Page cache The finished HTML of a page A plugin, or your host at server level
Object cache The results of database queries A persistent backend — Redis or Memcached — plus a drop-in
Browser cache Static files on the visitor's device HTTP headers from your server
Edge cache / CDN Copies near the visitor A CDN in front of your site

Most "caching problems" are one of two things: a missing layer, or two plugins doing the same layer.

Start by finding out what you already have, because a great many managed hosts run a page cache at server level, and installing a caching plugin on top of it is the single most common way to make a WordPress site slower and stranger at the same time.


Why this matters more than it sounds

WordPress does not mince words about the consequences of no caching at all:

"if you don't use a caching solution, performance will slow to a halt as additional page requests come in and stack up, often crashing your web or database server."

That is not a speed argument, it is an availability one. Caching is what stops a traffic spike turning into an outage.

And on the upside, WordPress's own optimisation guidance says caching "will cache your WordPress posts and pages as static files" and can improve performance "several hundred times over for fairly static pages" — while calling it "the biggest benefit for the smallest hassle."


Layer 1 — Page caching

What it does: stores the finished HTML so the next visitor gets a file instead of a PHP process and a dozen database queries.

This is the layer with the largest effect for a content site, and for most WordPress blogs it is the only one that is strictly necessary.

What it does not cache, by design:

  • Logged-in users, because their page is personalised
  • Carts and checkouts, and anything else session-dependent
  • Anything with query parameters, on most configurations
  • Forms and dynamic widgets, unless the cache supports fragment exclusion

The two rules:

  1. Run exactly one page cache. Server-level or plugin, not both
  2. Know what invalidates it. Publishing a post should clear the affected pages; a comment usually should too; a price change certainly should

How to check whether you already have one: load a page in a private window and look at the response headers for a cache header — x-cache, cf-cache-status, x-litespeed-cache and similar are all page caches announcing themselves. If one is present, you have this layer, and a caching plugin's page-cache module should stay off.


Layer 2 — Object caching

What it does: stores the results of database queries in memory so WordPress does not ask the same question repeatedly within and across requests.

WordPress's own framing: "Using a persistent Object Cache helps speed up page load times by saving on trips to the database from your web server."

The word doing the work is "persistent." WordPress always has an object cache — but by default it lives only for the duration of a single request, so nothing carries over. A persistent object cache keeps it in Redis or Memcached between requests, which is where the gain is.

This is the layer that matters most for the pages a page cache cannot serve: the admin, logged-in users, WooCommerce carts, membership areas. A shop or membership site with no persistent object cache is doing the same database work on every single request from every logged-in user.

For a small brochure site it is close to irrelevant. For anything with logged-in users it is often the largest available win, and it is the one most speed guides skip entirely because it usually needs the host to provide the backend.


Layer 3 — Browser caching

What it does: tells the visitor's browser to keep static files — images, CSS, JavaScript, fonts — instead of re-downloading them.

It does nothing for a first-time visitor and a great deal for a returning one, which is worth remembering when a test tool complains about it. Your PageSpeed test is always a first-time visitor.

It is configured with HTTP headers, not usually with a plugin. Most hosts set sensible defaults; a CDN will normally override them.

The one thing to get right is versioning. Long cache lifetimes are only safe when file names change on update — which WordPress handles for enqueued assets through the version query string, and which is why hand-linked files in a theme are the ones that go stale for returning visitors.


Layer 4 — Edge caching and CDNs

What it does: keeps copies of your files, and sometimes your pages, on servers near your visitors.

Two distinct jobs, often confused:

  • A CDN for static assets serves images, CSS and JS from a nearby location. Nearly always worth it
  • Full-page edge caching serves the HTML itself from the edge. A much bigger win — it can remove your server from the path entirely — and a much bigger source of surprises, because now cache invalidation happens somewhere you do not control

The rule for full-page edge caching: be sure you can purge it, and be sure it is excluding logged-in sessions and carts. This is where "I updated the page and it still shows the old version" comes from.


The fifth thing, which is not caching

Transients get filed under caching and behave differently enough to deserve a warning.

A transient is a value stored with an expiry — WordPress describes the API as "very similar to the Options API but with the added feature of an expiration time." Plugins use them constantly, for API responses, feed data, and computed values.

The part that catches developers, in WordPress's own words:

"transient expiration times are a maximum time. There is no minimum age. Transients might disappear one second after you set them, or 24 hours, but they will never be around after the expiration time."

So expiry is a ceiling, not a promise. WordPress adds that "it is possible for the transient to not be available before the expiration time", and that "your code should have a fall back method to re-generate the data if the transient is not available."

And with an external object cache, transients may not be in the database at all — WordPress warns never to assume they are stored there. Which is why "delete the transients from wp_options" is advice that does nothing on a site running Redis.

The practical version for a site owner: an accumulation of expired transients in wp_options is a symptom of a plugin behaving badly, and it is worth checking against the autoload figure in how to audit your WordPress plugins.


The newest layer: speculative loading

WordPress 6.8 shipped speculative loading in core, using the Speculation Rules API. The browser starts loading a page before the visitor has finished clicking the link to it.

The default is deliberately cautious: prefetch mode with conservative eagerness, which means "prefetching is triggered when a user starts to click on a link." WordPress chose it as "a reasonable starting point to enable speculative loading at the scale of WordPress", because it "minimizes the chance of any speculative loads without a subsequent navigation to the URL."

Where it does not apply, by default:

  • Logged-in users
  • Sites with pretty permalinks disabled
  • Any URL containing query parameters, which are "excluded from prefetching and prerendering automatically"

And the caveat if you turn it up. In prerender mode, "even their client-side code will be loaded" — so analytics, chat widgets and anything else client-side may fire for a page the visitor never actually opened, unless that code checks whether it is being prerendered first.

Treat the default as the setting. The aggressive modes are for people who can audit their own third-party scripts.


Setting the layers up, in order

Six steps.

Step 1 — Find out what you already have

Check the response headers in a private window for a cache header. Check your host's control panel for a caching or performance section. Check whether a caching plugin is already installed, including one bundled by your host.

This step exists because skipping it is how sites end up with two page caches.

Step 2 — Get exactly one page cache running

Server-level if your host offers it; a plugin if not. If both exist, turn off the plugin's page-cache module and leave the rest of its features alone.

Step 3 — Add a persistent object cache if you have logged-in users

Requires Redis or Memcached from your host, plus a drop-in to connect WordPress to it. Skip this entirely if your site is a brochure site with no logged-in traffic — it will do almost nothing.

Step 4 — Confirm browser caching headers on static assets

Usually already correct. Worth confirming rather than configuring.

Step 5 — Put a CDN in front of static assets

Then, only if you are confident about purging, consider full-page edge caching — and exclude logged-in sessions, carts and checkouts explicitly.

Step 6 — Test as a logged-out visitor, twice

Private window, first load and second load. Then log in and check the site still behaves. Then buy something, if you have a shop.

That last one is not optional. Cache misconfiguration on a WooCommerce site shows up as one customer seeing another's cart, and it is discovered by testing or by complaint.


When caching is the problem

Symptoms that mean the cache, not the code:

  • Changes not appearing after publishing or editing
  • Logged-in users seeing the logged-out version, or the wrong user's name
  • A cart that empties or shows someone else's items
  • Forms failing with a nonce or security error, because a cached page carried a stale token
  • The admin bar appearing for visitors who are not logged in

The first diagnostic is always the same: purge everything, at every layer, then retest. If the symptom disappears, it was cache. If it returns on a schedule, something is caching a page it should be excluding.

And if a page will not stop being wrong, work outwards: plugin cache, server cache, CDN. The layer you forgot is usually the outermost one.


Frequently asked questions

What is WordPress caching?
Storing the result of work so it does not have to be repeated. There are four layers: page caching stores finished HTML, object caching stores database query results, browser caching stores static files on the visitor's device, and edge caching stores copies near the visitor.

Do I need a caching plugin if my host has caching?
No — you should not run two page caches. If your host caches at server level, leave the plugin's page-cache module off. Check your response headers for a cache header to find out which you have.

What is a persistent object cache in WordPress?
An object cache that survives between requests, backed by Redis or Memcached. WordPress always has an in-request object cache, but without a persistent backend nothing carries over. It matters most for logged-in traffic, which a page cache cannot serve.

Why are my changes not showing on my site?
Almost always caching. Purge every layer — plugin, server, CDN — and retest. If the change appears, one of those layers was holding a stale copy; the layer people forget is usually the CDN.

Do transients expire exactly when I set them?
No. WordPress states that expiration times are a maximum with no minimum age — a transient might disappear a second after being set. Code using them needs a fallback to regenerate the data if it is missing.

Can caching break WooCommerce?
Yes, if carts, checkouts and account pages are not excluded. The symptoms are shared carts, stale prices and failed checkouts. Always test a real purchase after changing any caching layer.

What is speculative loading in WordPress?
Core support, added in 6.8, for loading a page before the visitor finishes clicking. The default is prefetch with conservative eagerness, disabled for logged-in users and sites without pretty permalinks, with query-parameter URLs excluded automatically.

Is prerendering safe to enable?
Only with care. WordPress warns that in prerender mode even client-side code is loaded, so analytics and widgets can fire for pages nobody visits unless that code checks whether the page is being prerendered first.


What to do next

Open your site in a private window and look at the response headers for a cache header. That one check tells you whether you already have a page cache and therefore whether you need a caching plugin at all.

If a header is there and a caching plugin is also running its own page cache, turning one of them off is likely the fastest improvement available to you today.


Related guides

The short version

  1. Find out what you already haveCheck response headers in a private window for a cache header, check the host's control panel, and check for a bundled caching plugin. Skipping this is how sites end up with two page caches.
  2. Get exactly one page cache runningServer-level if your host offers it, a plugin if not. If both exist, turn off the plugin's page-cache module and leave its other features alone.
  3. Add a persistent object cache if you have logged-in usersRequires Redis or Memcached plus a drop-in. Skip it for a brochure site with no logged-in traffic u2014 it will do almost nothing.
  4. Confirm browser caching headers on static assetsUsually already correct, and worth confirming rather than configuring. Long lifetimes are only safe when file names change on update.
  5. Put a CDN in front of static assetsConsider full-page edge caching only if you are confident about purging, and exclude logged-in sessions, carts and checkouts explicitly.
  6. Test as a logged-out visitor, twice, then logged inPrivate window, first and second load. If you run a shop, complete a real purchase u2014 cache misconfiguration shows up as one customer seeing another's cart.

The WordPress Email Delivery Checklist

Stop your WordPress emails from failing silently. Get the complete setup guide.

Muhammad Basim

About the Author

Muhammad Basim

Digital Marketer & WordPress Developer

Muhammad Basim has worked in digital marketing since 2013, focused on email deliverability and AI-assisted content production. He is the author of The Email Deliverability Playbook and The Email Copywriting Playbook.

Related Articles

Newsletter

Free: The 60-Minute
Email Authentication Fix

A no-fluff checklist from the Deliverability Playbook. In one hour: set up SPF, DKIM & DMARC correctly, check your domain against blocklists, and pass Gmail & Yahoo's 2026 sender requirements.

No spam — that would be ironic. Unsubscribe anytime.