Cache Rules Everything Around Me. Or: How WordPress Learned To Hide The Body.
There is a particular flavour of email that lands in every freelance inbox on a Monday morning. The client has run their site through PageSpeed Insights over the weekend, scored a confident 38 on mobile, and would like to know — politely, because they are British and it is before nine — what you are going to do about it. You already know what you are going to do about it. You are going to install another caching plugin. Possibly two. You are going to enable a CDN that was already enabled. You are going to tick a box marked 'Critical CSS' and watch the navigation menu render in Comic Sans for forty minutes while the regeneration queue grinds through. And then the score will go up, and the client will be happy, and the site will still be slow, and you will know, in the quiet part of your brain that you keep locked because the mortgage is due, that you have not actually fixed anything. You have just moved the problem behind a curtain.
This is the central confession of the WordPress performance industry, and it is past time somebody made it on the record: advanced caching, in 2026, is not engineering. It is stagecraft. It is a magic trick performed on a synthetic test by a developer who is being paid by the hour to make the trick work. The site behind the curtain is still the site it always was — a PHP application invented in 2003 to render personal weblogs, retrofitted into a CMS, retrofitted again into an ecommerce platform, retrofitted a third time into a page builder, and now propped up by six concurrent layers of cached output because anything less and the whole apparatus falls over the moment a real human clicks 'Add to Cart' from a mobile network in a lift.
Count the layers. Then count them again.
A normally configured 'fast' WordPress site in 2026 has, at minimum, the following caches running concurrently. Page cache, generated by WP Rocket or LiteSpeed or W3 Total or Nitropack or FlyingPress, writing flat HTML files to disk so PHP does not have to run on every request. Object cache, usually Redis or Memcached, sitting in front of the database so MySQL does not have to think too hard about whether the user is logged in. Opcode cache, which is OPcache, baked into PHP itself, holding compiled bytecode in memory so the interpreter does not re-parse the same plugin files seventeen times a second. Browser cache, set via headers, telling Chrome to keep the logo for a year. CDN edge cache, at Cloudflare or BunnyCDN or KeyCDN, holding the page in fifty data centres so the visitor in Lisbon does not have to fetch from your London origin. And on top of all of that, a fragment cache inside the theme or builder, because Elementor widgets render slowly enough to need their own private cache, separate from everything else.
Six layers. Six places a stale version of the page can hide. Six places that have to be invalidated, in the correct order, the moment somebody changes a comma in a heading. Six places that, when the client logs in to update their phone number in the footer, can independently decide to keep serving last Tuesday's version of the site for the next nine hours. The mental model required to debug this stack is not the mental model of a web developer. It is the mental model of a forensic accountant. You are not building. You are reconciling.
“There are two hard problems in computer science: cache invalidation, naming things, and off-by-one errors. WordPress solves all three by adding a seventh cache.”
Then the page builder shows up with a wheelbarrow of inline styles.
Elementor is not the only offender, but Elementor is the canonical one, so let us speak plainly about Elementor. A blank Elementor section, with no content in it, ships approximately seven kilobytes of inline CSS scoped to a generated class name like .elementor-element-7a3f9c2. Add a heading widget. Now it is twelve kilobytes. Add a two-column inner section with a button. Now it is twenty-eight. Build a homepage with a hero, three feature cards, a testimonial slider, a logo strip and a footer CTA — a layout a junior designer could build in raw HTML in an afternoon and serve as a fourteen kilobyte gzipped document — and you are now shipping somewhere between three hundred and seven hundred kilobytes of CSS, half of it inline, the other half split across a dozen render-blocking stylesheets named like elementor-post-247.css, elementor-pro-icons.css, and the eternal favourite, elementor-frontend.min.css, which weighs more than the entire Stripe checkout SDK.
Now add the JavaScript. Elementor's frontend script. Elementor Pro's frontend script. Swiper, because there is a carousel somewhere. Waypoints, because something animates on scroll. jQuery, because Elementor still depends on jQuery in 2026 and shows no sign of stopping. jQuery Migrate, because the WordPress core team is still pretending somebody might be running a 2014 plugin in production. A custom IntersectionObserver polyfill nobody has needed since 2019. Google Fonts loaded synchronously from fonts.googleapis.com on the off chance the local font preload did not fire. The total weight of the page, before a single byte of actual content has been served, is north of a megabyte. The Largest Contentful Paint element is the hero image. The Total Blocking Time is whatever number makes you cry.
This is the page the caching plugin is being asked to make fast. Not a slim, semantic document with a job to do — a baroque assemblage of nested div soup, generated class names, and inline style islands, every section of which was built in a visual editor that prioritises drag-and-drop convenience over output discipline. No amount of edge caching changes the fact that the browser, on first paint, has to parse, deduplicate, and compute styles for a CSS payload that would have been considered architecturally negligent at any point in the last ten years. Caching does not make the payload smaller. It just stops your server having to assemble it from scratch on every request. The visitor still downloads all of it. The visitor's phone still has to render all of it. The visitor's battery still pays for all of it.
Critical CSS is a confession dressed as a feature.
Pause on this one, because it is the most telling artefact in the entire stack. 'Critical CSS' is the technique of identifying which stylesheet rules apply to the content above the fold on first paint, inlining those rules into the HTML so the page can render before the main stylesheet arrives, and deferring the rest. Every serious WordPress caching plugin ships this feature, usually as the marquee item in the Pro tier. WP Rocket calls it Remove Unused CSS. LiteSpeed calls it CCSS. Perfmatters offloads it to a third-party API. Nitropack rebranded it as Smart Cache Invalidation, because Nitropack rebranded everything.
Stop and consider what this feature is actually admitting. It is admitting that the stylesheet your CMS produced is so bloated, so undisciplined, so unrelated to what any individual page actually needs, that the browser cannot be trusted to download and apply it in time to render the page. The fix is not 'produce a smaller stylesheet'. The fix is 'have a robot scan the rendered page, guess which 8% of the rules are needed for the first viewport, inline those, and quietly load the rest later, hoping nobody scrolls fast enough to notice the jank'. This is not optimisation. This is triage performed on a patient who was perfectly healthy until WordPress put a forty-pound rucksack on its back.
A site built in 2026 on a modern framework — Astro, TanStack Start, SvelteKit, Eleventy with a sensible CSS layer, even a plain hand-written HTML page with one stylesheet — does not need critical CSS extraction. It does not need critical CSS extraction because the stylesheet was small enough to begin with. It did not need a Pro plan to be small. It needed a developer who understood that CSS is a payload, not a kitchen drawer.
Cache invalidation, or: the day the prices were wrong for nine hours.
Here is the part that does not show up in any tutorial, any plugin's marketing page, or any 'how I got to 100 on PageSpeed' YouTube video. It is the part that shows up in your Slack at 6:47pm on a Friday, when the client has just realised that the product they updated this morning is still showing yesterday's price on the category page, the homepage carousel, and Google's cached snippet. Six caches. Six independent invalidation policies. WP Rocket purges its own page cache when a post is saved, but not when a WooCommerce product is updated unless you tick the right box. The object cache, if it is Redis, has a thirty-second key TTL that somebody set in 2021 and nobody has revisited. Cloudflare's cache, if it is on Automatic Platform Optimisation, holds the HTML for an hour regardless of what the origin says, because that is what APO is for, and the purge webhook has been silently failing since the SSL certificate on the origin renewed and the cipher suite changed.
The fragment cache inside Elementor is the worst of them. It caches the rendered HTML of individual widgets, keyed by post ID and a hash of the widget settings, and it does not always notice when a global widget — like a header or a footer — has been edited, because the cache key does not include the global widget's revision number. The result is that you change the phone number in the footer, you flush every cache you can find, you clear Cloudflare, you SSH in and run a manual wp cache flush, and the old phone number is still on twelve product pages and the about page, because Elementor's fragment cache regenerated those pages between your edit and your purge and is now serving its own snapshot with the old phone number baked into the HTML. The fix is to regenerate every Elementor cached CSS file, which is a tickbox somewhere in Elementor > Tools > Regenerate CSS & Data, and to wait. And to lie to the client about why it took until Sunday.
This is not a hypothetical. This is the lived experience of every agency owner who has ever inherited a WordPress site they did not build. It is the reason 'WordPress maintenance retainer' exists as a line item. It is the reason your Friday is not your own.
The honest definition of 'advanced caching'.
Strip the marketing language away and 'advanced caching' on WordPress means one of three things. It means full-page HTML caching at the edge, which any half-decent CDN does for static content for free, and which only feels advanced because WordPress is dynamic by default and has to be coerced into producing cacheable HTML. It means object caching with Redis, which is a sensible solution to a problem your CMS should not have — namely, that rendering a simple page requires forty database queries because the plugin ecosystem has trained everyone to store settings as autoloaded options. Or it means generating critical CSS, lazy-loading images, deferring scripts and minifying everything, all of which are workarounds for the fact that your stack produces too much CSS, too much JavaScript, and too many render-blocking resources in the first place.
Each of these is a legitimate engineering technique. None of them is novel. None of them is exclusive to WordPress. All of them are necessary on WordPress in a way they are not necessary on a modern static or edge-rendered stack, because the modern stack does not generate the problem the caches are solving. The cache is not making your site fast. The cache is making your site less catastrophically slow than it would be if you turned the cache off. Those are different things, and the people selling the cache plugins are very careful never to say so.
“If you have to cache the cache, you do not have a fast site. You have a slow site with a good publicist.”
The test that nobody runs.
There is one diagnostic that settles this debate every time, and almost no agency runs it, because the answer is professionally inconvenient. Take your cached WordPress site, the one scoring 92 on mobile PageSpeed. Open the WP Rocket settings, or LiteSpeed, or whatever is doing the heavy lifting. Disable page caching. Disable critical CSS. Disable JS deferral. Disable lazy loading. Disable everything. Now run PageSpeed Insights again on the uncached page. Look at the number.
That number — usually somewhere between 14 and 32 on mobile — is your site's actual performance. The 92 is theatre. The 14 is the truth. Every millisecond of difference between those two scores is being paid for, on every single request, by a tower of caching infrastructure that has to be maintained, monitored, purged, regenerated, and explained to the client when it breaks. You have not built a fast site. You have built a slow site wearing a fast site as a costume, and the costume needs dry-cleaning every time you change a heading.
Run the same test on a modern stack — a TanStack Start app on Cloudflare, an Astro site on Netlify, a plain HTML brochure on a static host. Turn off the CDN. Turn off everything. The score barely moves, because there was nothing to cache that the framework had not already eliminated at build time. There is no costume. The site is just fast. Naked, on a cold cache, with no plugin in sight, it scores 96 on mobile because the document is twelve kilobytes and the JavaScript is forty.
What we are actually selling when we sell 'WordPress optimisation'.
Be honest, for a moment, about the work. A WordPress speed optimisation engagement, in 2026, is a £600 to £2,400 invoice in which the deliverable is: a Cloudflare account, a WP Rocket licence, an afternoon of configuration, a screenshot of a green PageSpeed number, and a polite note explaining which caches to purge in which order when the client wants to update content. None of that is engineering. All of it is sticking-plaster work performed at a senior engineer's hourly rate, on a platform that needed the sticking plaster because of choices made by Automattic, by the plugin economy, and by the client when they were sold an Elementor theme three years ago by somebody else who has since stopped answering email.
- →You are not making the site fast. You are making the slowness less visible to a synthetic Lighthouse run.
- →You are not reducing the payload. You are caching, deferring, and lazy-loading a payload that should never have been generated.
- →You are not solving a performance problem. You are inserting yourself, billably, into the recurring task of managing the consequences of one.
- →You are not building the future of the site. You are building the maintenance retainer that pays for the school holidays.
This is not a moral failing. The clients are happy. The invoices clear. The PageSpeed badge sits proudly in the footer. But it is worth being clear-eyed, internally, about what you are actually being paid for, because the moment a client realises they can rebuild the same brochure site on a modern framework, host it on the free tier of a CDN, and never need a caching plugin again, the entire revenue stream evaporates. And they will realise it. They are already realising it. The Lovable build is sitting on a preview URL. The Webflow proposal is open in another tab. The 'AI built my whole site in forty minutes' video is in the YouTube recommendations.
The harder, more honest pitch.
Stop selling caching. Start selling architecture. The next time a client comes to you with a slow Elementor site and a screenshot of a 38 on PageSpeed, do not quote them for a WP Rocket configuration. Quote them for the conversation that ends in: this site will never be fast, because of what it is. We can spend £1,800 making the synthetic score green, and you will be back here in fourteen months when the next plugin update breaks the cache layer. Or we can spend £6,000 rebuilding the front end on a stack that does not need a cache to be fast in the first place, and you will never email me about PageSpeed again. Here are the trade-offs. Here is the timeline. Here is what your team needs to learn.
That is the conversation that pays for the next decade. The caching conversation is the conversation that paid for the last one, and it is closing for business whether the WordPress community is ready or not. Advanced caching was always a confession. The mistake was treating it as a credential.
Flush the page cache. Flush the object cache. Flush the edge cache. Flush the fragment cache. The site is still slow. It was always going to be slow. The cache was the apology, not the fix.
Found this useful? Argue with it.
More Heresies →