DEV Community

Cover image for After 3 Years of Managing WooCommerce Stores, I Found the Bug Cache Plugins Can't Fix
Sarp Efe
Sarp Efe

Posted on

After 3 Years of Managing WooCommerce Stores, I Found the Bug Cache Plugins Can't Fix

Here's a scene I've played out dozens of times:

A client DMs me. Their shop is slow. Checkout takes 4 seconds on a good day. They've already paid for WP Rocket. They've already paid for a decent managed host. They can't figure out what's wrong, and they've started to suspect WordPress is "just slow."

So I log in, crack open Query Monitor, and stare at the numbers for a while.

Every single time, the answer was the same. And it was never where anyone expected.


What I kept trying first (and why it kept failing)

For years, my debugging playbook for a slow WooCommerce site went like this:

  1. Install WP Rocket. Page cache, preload, minify. Usually helped the homepage.
  2. Check the CDN. Sometimes Cloudflare had a weird origin rule.
  3. Minify CSS/JS. Autoptimize or Perfmatters.
  4. Upgrade the hosting plan. The "throw money at it" phase.
  5. Blame WooCommerce.

Step 1 fixed the homepage. Step 2 shaved TTFB for anonymous visitors. Step 3 chipped off 200ms on LCP. Step 4 rarely made a real difference once a store was above basic shared hosting. Step 5 was cope.

But here's the thing. The pages clients actually cared about — cart, checkout, my-account, any logged-in view — never got meaningfully faster.

Why? Because all of those pages are per-user. They can't be cached. Every request runs the full PHP pipeline from scratch, and no amount of page cache or CDN fixes that.

If your cart page is slow after installing WP Rocket, it's not WP Rocket's fault. It's not built to help there.


The moment it finally clicked

One day I was profiling a site with about 38 active plugins. Real store, real traffic, around 120K monthly pageviews. The owner was about to migrate to Shopify because they "couldn't take it anymore."

I ran Query Monitor on the cart page. The database queries looked fine. Templates rendered fast. Nothing obvious.

Then I looked at the hook timeline.

Before WordPress had even finished firing init, 35 plugins had already executed code.

Every. Single. Request.

  • Their Mailchimp integration booted on every page view, even when nobody was subscribing.
  • Their Wordfence fired on every admin-ajax call, including the cart fragments refresh that runs every few seconds.
  • Their Elementor Pro loaded its full runtime on a WooCommerce REST API request that had nothing to do with Elementor.
  • Their Google Listings sync module spun up on every frontend request, even though the actual sync only runs on cron.

The total? About 410ms of PHP execution before WordPress even started pulling the cart contents.

Four hundred and ten milliseconds. On every single request. Just for plugins that were doing nothing useful on that page.


Why nothing else fixes this

Here's the uncomfortable part. Once I saw this, I started looking at it on every site I managed. It was always there. And every tool I was using had a blind spot:

  • WP Rocket / WP Super Cache / LiteSpeed Cache — Caches the output. If you can't cache the output (cart, checkout, logged-in users), it does nothing.
  • Perfmatters — Great for dequeuing CSS and JS per page. But the plugin itself still boots. Its PHP still runs. You save bytes, not execution time.
  • Query Monitor — Shows you the problem beautifully. Doesn't fix it.
  • Object cache (Redis) — Helps get_option lookups. Doesn't stop a plugin's plugins_loaded hook from running.
  • Upgrade hosting — Gives you a faster CPU to run the same wasted code on.

None of them stop plugins from booting. They all accept the boot overhead as a given and optimize around it.


What I actually built

Honestly, at first I tried to solve this the manual way. I'd write mu-plugin code per client that would unhook a specific plugin on a specific request class. It worked, but it was bespoke for every site, fragile, and nobody else on my team could maintain it.

After the fifth client, I got tired of it and built a real tool.

The idea is embarrassingly simple:

Before WordPress loads its plugins, look at the incoming request. Decide which plugins are actually relevant to this request. Don't load the rest.

Jetpack doesn't need to boot on a cart AJAX refresh. FluentSMTP only needs to boot when an email is being dispatched. Your backup plugin doesn't need to live in memory during a REST API call for product stock.

So you look at the request class — frontend guest GET, frontend logged-in, REST API, admin-ajax, admin, cron — and you skip the plugins that aren't needed.

That's the whole thesis.

I shipped it as Accelerator. The current version (v0.2.0.1) ships with a library of rules for 207 of the most common WordPress plugins, so you don't have to figure out the matrix by hand. There's a setup wizard that scans your site, suggests which plugins can be safely unloaded on which request classes, and runs everything in Shadow Mode first — meaning it measures the gain for 24 hours without actually changing anything, so you can see the impact before you commit.

On my own production site, the frontend guest GET p50 went from 715ms to 271ms. A 62% reduction, 444ms absolute. Measured, not estimated — the tool ships with a telemetry dashboard that tracks before/after per request class.


The honest part

This isn't for every WordPress site. If I were writing a pure marketing post I'd leave this out, but I'm not, so:

  • If your site runs fewer than ~10 plugins, the gain is marginal. You don't have enough boot overhead to matter.
  • If you're on WordPress.com, you can't install custom plugins, so it's moot.
  • If your real bottleneck is the database (10,000-product WooCommerce store on overloaded MySQL), this won't help you there. Different problem.
  • If you're on oversold shared hosting, upgrade the host first.
  • If you're shopping for "the cheapest performance plugin," it's not built for that segment.

The tool works best on WooCommerce stores running 20-40 active plugins. Which, in practice, is most of them.


What I wish someone had told me three years ago

If you're managing a WooCommerce store and WP Rocket hasn't been enough, stop stacking more cache layers. The plugins you've accumulated over the years are quietly loading on every single request. That's the tax you're paying.

You have three options:

  1. Audit and prune aggressively. Go through every plugin. Ask "is this running on every request? Does it need to?" Remove the ones you can. This is the free option. It's also the most painful, and it has a floor — at some point you do need those plugins, just not on every request.

  2. Write per-site code to unhook them conditionally. This is what I did for years. It works. It doesn't scale.

  3. Use a tool that does this systematically. Whether it's mine or not, the category exists now. Look for anything that talks about "conditional plugin loading" or "request-class awareness." Don't accept substitutes that only cache output — that's a different layer and it doesn't reach the pages that matter.

Whichever route you take, the important thing is to stop blaming WordPress for a problem that lives one layer above it.


If you're curious about the tool, Accelerator is here. It's in closed beta right now. If you're running a WooCommerce store with a heavy plugin stack and you want to help me stress-test it on a real site, reply in the comments or email me at sarp@for-wordpress.org. I'm manually onboarding testers and I'll walk you through the setup.

Happy to answer technical questions about the approach in the comments — especially if you've hit this bottleneck and solved it a different way. I want to hear it.

Top comments (0)