Every WordPress performance debate eventually arrives at the same line: just put the site behind a proper edge cache. Cloudflare, Varnish, NGINX FastCGI cache, your host's built-in edge — let WordPress not run at all. That solves it.
The argument is correct as far as it goes. It's also incomplete in a way that turns out to matter more than the part it gets right, and the place that incompleteness shows up first is usually the highest-revenue page on the site.
Edge caching is the best single performance technique WordPress has. If you can serve a request from an edge cache without WordPress booting, you absolutely should — the TTFB drops to 20–80ms regardless of how slow your origin is, and the PHP load on your hosting drops by 70–90% on a typical content site. None of what follows argues against that. You should configure edge caching on every site that supports it.
The "alone" in the title is doing the work. On a real WordPress site — particularly one running WooCommerce, a membership plugin, an LMS, or anything that puts customers behind a login wall — somewhere between 5% and 60% of traffic by request count is fundamentally uncacheable at the edge. That fraction is what the rest of this post is about. Honest disclosure since I always include one: I run AcceleratorWP, a plugin whose entire job is making the uncacheable half cheaper. I'll explain how briefly at the end. Everything before that holds regardless of which tool you end up using.
What edge caching actually does
The mechanism, in one paragraph: the first visitor hits a URL, the request reaches your origin, WordPress boots and generates HTML, your edge cache (Cloudflare / Varnish / KeyCDN / host CDN — pick one) stores the HTML keyed by URL, and every subsequent visitor on the same URL gets the stored copy from the nearest edge POP. WordPress doesn't run for them. The TTFB is whatever the network round-trip is.
This is great for content that doesn't change per visitor: blog posts, product listings, marketing pages, category and tag archives. On a brochure site or a blog, 90–98% of visitor requests fall into this bucket. Configuring edge caching properly on those is the single largest performance win you'll ever get. Once it's set up, it costs you nothing in ongoing complexity.
The plugin ecosystem reflects this. WP Rocket, LiteSpeed Cache, NitroPack, WP Super Cache — most of their feature surface is generating cacheable static HTML files. The full survey of cache-free performance methods covers why you'd care about anything else; this post is framed from the other direction.
The requests edge caching does not help
A request is uncacheable at the edge if the response depends on something the edge cache doesn't know about — typically the user's identity, the cart state, a session token, or a piece of live data that changes per visitor. Every serious cache plugin and every serious edge cache respects this. The five categories that come up on real sites:
1. Logged-in users
The moment a visitor logs in, every cache layer backs off. WP Rocket bypasses its page cache for logged-in users by default. Cloudflare's "Cache Everything" rule excludes requests carrying a wordpress_logged_in_* cookie. LiteSpeed Cache keeps a separate cache group for logged-in users and only serves a small subset of pages from it.
On a content blog this affects nobody — the only logged-in users are the editors. On a membership site, an LMS, or any site where customers maintain accounts they revisit, logged-in traffic is 40–70% of total page views. Every one of those visits misses the edge cache entirely.
2. WooCommerce checkout, cart, and my-account
WooCommerce explicitly sends Cache-Control: no-store, no-cache, must-revalidate headers on these pages. Not a misconfiguration — deliberate. A cached checkout serves stale shipping rates, expired nonces, and product prices from before the visitor applied their coupon. Every serious cache plugin reads the headers and excludes the URLs by default; WP Rocket ships with /checkout/ and /cart/ in its exclusion list out of the box.
On a WooCommerce store the highest-revenue page on the site — the checkout — pays the full WordPress boot cost on every single load. There's no clever cache configuration that fixes this without breaking orders. The WooCommerce slow checkout post walks through what actually moves TTFB on those uncached pages.
3. REST API endpoints
/wp-json/wc/v3/orders, /wp-json/wp/v2/posts?_embed, /wp-json/wc/store/v1/checkout, /wp-json/wp/v2/users/me — REST endpoints are hit by headless front-ends, mobile apps, the Gutenberg block editor, integration scripts that poll your store, and increasingly by the WooCommerce block-based checkout (the default since WooCommerce 8.3).
Some REST responses can be cached if the resource is fully public and stable, but most aren't. Cart state, order data, user profiles, admin operations — all of these need to hit a live WordPress instance. The edge passes them through.
4. admin-ajax.php
The legacy AJAX endpoint. Fires on every WooCommerce front-end page (the wc-ajax=get_refreshed_fragments call). Fires on every block editor save and every autosave. Fires on most form submissions from front-end form plugins. Fires on background work from security, SEO, and analytics plugins.
A typical page view on a WooCommerce site generates 2–4 admin-ajax requests on top of the page request itself. Each is a full WordPress boot. None of them touch your edge cache.
5. wp-cron and background workers
Scheduled posts, nightly backups, sitemap regeneration, WooCommerce order email dispatch, Action Scheduler queues, abandoned-cart reminders, license heartbeats, plugin update checks — all run through /wp-cron.php or its replacement system cron. None of these are cache-relevant; the post on disabling wp-cron without breaking scheduled posts covers this corner specifically. Edge caches don't touch cron paths because the cron paths aren't visitor-facing in the way cache works.
How big is the uncacheable half, really
It varies enormously by site type, and that variance is the part most "use edge cache" recommendations skip past.
- Brochure site, blog, content marketing site: 2–8% of requests bypass the edge. Edge caching basically solves the problem.
- News site with comments, member-only premium articles: 10–20%. Edge caching helps a lot, doesn't finish the job.
- WooCommerce store, classic theme, no subscriptions: 25–35%. The checkout pays full freight on every load; admin-ajax fires on every visitor page.
- WooCommerce store with subscriptions, customer dashboard, REST API integrations: 35–55%. Most of the high-revenue traffic is uncacheable.
- Membership site, LMS, customer portal: 60–80%. The cache helps the marketing pages and basically nothing else.
If your site is in the bottom two categories, edge caching alone is not your performance answer. Not because edge caching is wrong — but because the requests that can be cached weren't the slow ones in the first place.
"Just use better plugins" — why this doesn't ship
The honest objection to plugins like AcceleratorWP, and the one that comes up in every performance discussion, is that the real fix is to choose plugins that don't load themselves everywhere they're not needed. If Yoast loaded only on pages where its output is rendered, you wouldn't need a plugin to skip it. If WooCommerce only initialised its cart session on cart-adjacent pages, the boot cost would shrink itself.
The objection is correct in principle. In practice it doesn't ship, for three reasons:
One: the plugin you'd need to replace is the one your client already picked. Yoast has 5M+ active installs. Rank Math has 3M+. Elementor has 5M+. WooCommerce itself is on 6M+ stores. "Just use a better-built alternative" means rebuilding the editorial workflow, retraining the team, migrating settings, and probably re-doing block templates. Performance optimisation that requires a plugin migration isn't optimisation — it's a quarterly project.
Two: the well-built alternatives often don't exist in the categories where it matters. There's no SEO plugin at WordPress-scale market share that's genuinely contextual about when it runs. There's no e-commerce plugin at WooCommerce's scale that loads its full stack conditionally. The market preferred features over performance discipline for fifteen years and the popular plugins reflect that. Even the "lean" alternatives tend to load themselves globally; what differs is how much code runs per request, not whether it runs at all.
Three: WordPress itself doesn't help. The plugin loading mechanism in wp-settings.php reads active_plugins, then loads every plugin's main file on every request. No conditional logic, no URL awareness, no request-type detection at this layer. Plugins can throttle their work once they're loaded, but they can't avoid being loaded. Fixing this in WordPress core would be a multi-year ecosystem migration touching every plugin author's release process. The mu-plugin layer is the only intervention point that exists before plugin loading happens.
The deployable answer is: yes, in an ideal world plugins would load themselves correctly. In the world that actually exists, you have someone else's plugin stack on a site you didn't build from scratch, and you need a fix that works without rewriting every plugin author's code first.
A note on the "AcceleratorWP loads after WordPress anyway" objection
This one comes up specifically because the mu-plugin loading model isn't widely understood. The argument: AcceleratorWP is a plugin, plugins load after WordPress boots, so it's doing optimisation on top of the boot cost it claims to reduce.
The mechanical reality is different. AcceleratorWP is structured as an mu-plugin (must-use plugin) — WordPress loads everything in wp-content/mu-plugins/ before it reads active_plugins and starts loading the regular plugins. By the time wp-settings.php is about to enumerate active plugins, AcceleratorWP has already attached a filter to option_active_plugins. That filter intercepts the active plugin list and returns a reduced list for the current request, based on URL pattern, request class, and skip rules.
The result is that the plugins your site has installed but don't need on a given request literally do not load — their PHP files are never included, their classes are never instantiated, their hooks are never registered. That's the boot-cost reduction. WordPress core still loads, obviously. Your active theme still loads. But the irrelevant plugin subset never enters memory on requests where it has nothing to do.
This is not a bandaid on top of plugin loading — it's an intervention that happens before plugin loading. Whether you agree the architecture is the right answer is a separate question, but the "loads after WordPress anyway" objection misses where the mu-plugin layer sits in the boot sequence.
What actually moves TTFB on the uncacheable half
Three techniques, layered, in descending order of leverage:
Skip irrelevant plugins on uncacheable request classes. Your SEO plugin doesn't need to load on /wp-json/wc/v3/orders. Your social-sharing plugin doesn't need to load on admin-ajax.php. Your slider plugin doesn't need to load on /wp-cron.php. The per-page plugin loading post walks through the mu-plugin pattern, and the WooCommerce non-shop variant covers the e-commerce-specific footguns.
Prune hooks on plugins that have to stay loaded. Some plugins legitimately belong on a given request but register hooks for features that produce no output there. Jetpack registers social-sharing hooks on every page, including checkout. Yoast registers Open Graph hooks on REST responses where they're meaningless. Removing these hooks per-request gives you back execution time without removing the plugin.
Disable wp-cron on visitor requests and run it from a real scheduler. Don't let visitor traffic trigger your background work. Covered in detail in the wp-cron post.
These are what edge caching can't substitute for. They live below the cache layer, on the requests that bypass it.
A measurement
A WooCommerce store I work with regularly: 28 active plugins, Subscriptions and a custom membership integration, real EU traffic, Cloudflare in front with cache-everything-public properly configured.
Cloudflare cache hit ratio on incoming requests: 94%. Excellent. The 6% that miss are also the meaningful 6%:
- Checkout page TTFB: 1,920ms
wc-ajax=update_order_review: 940mswp-json/wc/v3/orders(subscription renewal endpoint): 1,420ms- Customer dashboard (logged-in
/my-account/): 1,640ms
After applying the structural techniques above — surgical plugin skipping per request class, hook pruning on the plugins that stayed, wp-cron decoupling:
- Checkout page TTFB: 490ms
wc-ajax=update_order_review: 280mswp-json/wc/v3/orders: 410ms- Customer dashboard: 510ms
Same Cloudflare configuration. Same 28 plugins still active on the cacheable 94%. The cache layer continues to do its job perfectly. The structural layer does the other job — making the 6% that bypasses the cache cheap enough to be tolerable on a phone with a 4G connection.
Neither layer substitutes for the other. The 94% cacheable rate gets you a fast homepage and fast product pages. The structural fix gets you a fast checkout and a fast dashboard. You need both for the store to actually feel fast end-to-end — and on the kind of site where the second number matters (any e-commerce, any membership, any LMS), the second fix is the one that affects revenue.
Where AcceleratorWP fits
Quick disclosure I owe: AcceleratorWP is what I make, and the second half of the measurement above is what it does. It runs at the mu-plugin layer — before WordPress loads any of your active plugins — and decides which of them should boot on each request class based on a profile generated by the setup wizard. Cacheable visitor pages on the edge side never reach the plugin; the optimisation only kicks in on the requests that bypassed your edge cache.
We don't cache anything. We don't try to compete with WP Rocket or LiteSpeed Cache or your Cloudflare configuration. The two compose: pick whichever edge cache and page cache your stack supports for the cacheable majority — the WP Rocket alternatives ranking and the NitroPack vs WP Rocket comparison both cover that side — then put AcceleratorWP underneath for what's left.
If your Cloudflare hit rate is 94% and your homepage is 80ms but your checkout is still pushing 2 seconds, the next thing to install isn't a different cache plugin. The cacheable problem is already solved. What's left is the structural one — and that's the conversation the "just use edge caching" advice keeps skipping past.
If you've tried structural optimisation on a real site and the numbers came out differently than what I described above, I'd genuinely like to hear about it. Send notes to my inbox. I update the measurement as new beta-tester data lands.

