DEV Community

NOGUCHILin
NOGUCHILin

Posted on

The biggest fix for this slow WooCommerce checkout was removing an optimization plugin (-60%, measured)

This is a real diagnosis for a real client. The site, niche, and anything identifying are deliberately left out. Every number is measured, not estimated.

TL;DR

  • A client's WooCommerce checkout took 6-8 seconds. A default theme dropped it to 1-2s, so "it's the theme" seemed obvious. It wasn't that simple.
  • My first hypothesis (PHP OPcache disabled) was wrong, and I told the client so instead of quietly finding a different smoking gun.
  • Profiling split the cost three ways: ~58% plugin/WooCommerce init, ~14% a synchronous API call, ~22% page-builder rendering. I told the client further plugin cleanup would be worth "a few hundred milliseconds."
  • That expectation was wrong too - in the good direction. Controlled A/B/A tests found one plugin whose deactivation took checkout from 4.6-4.7s to 1.68-1.73s (-60%). It was a performance optimization plugin.
  • Total silver bullets sold: zero. Total plugins removed: one - an optimizer.

The setup

Client's report: checkout takes 6-8 seconds on their WooCommerce store (heavyweight theme + WPBakery page builder). They'd already tried the obvious things - upgraded hosting, removed some plugins, simplified the checkout page. Still slow. Their own test: switch to a default WordPress theme, checkout drops to 1-2 seconds. Switch back, 6-8s again.

That test is genuinely useful data. It rules out "it's the network" and points hard at something in the theme/plugin stack. But "the theme is slow" isn't a diagnosis - it's a direction to start digging.

First hypothesis, and why I dropped it

My first read: PHP's opcode cache (OPcache) disabled, forcing the server to recompile a large theme + page-builder codebase on every request. It fit the symptoms, and it's a real, common cause on cheap hosting.

I said as much to the client, then went to actually check.

It wasn't that. OPcache was on and working. I could have quietly moved on and let the client believe "OPcache was the fix" once I found something else. I didn't, because the whole point of a paid diagnosis is that it's actually the reason, not a plausible-sounding one. Saying "my first theory was wrong, here's what's actually happening" costs a little credibility in the moment and buys a lot of it over the relationship.

What I actually did

Cloned the live site to a private staging copy (nothing touches production during diagnosis), then used Query Monitor to break down where page-generation time was going, plus temporary custom timers around suspect hooks.

[ ] Clone to staging, never touch production during diagnosis
[ ] Profile with Query Monitor: hook timings, query count, memory
[ ] Add temporary timers around suspect init/render stages
[ ] Rule things out explicitly (OPcache, Redis) - measure, don't assume
[ ] Test plugin changes as A/B/A with repeats, not A/B once
[ ] Only ship a fix once it's measured
Enter fullscreen mode Exit fullscreen mode

Ruling things out matters as much as finding the cause. Redis? Not available on that hosting plan at all (just an unused client library). Another plausible-sounding fix, closed off with one command instead of a paragraph of speculation.

What the time actually was

Stage Share What's really happening
Plugin / WooCommerce init ~58% (~3s) Every active plugin runs its setup code on every request - combined weight, not one villain
Synchronous API call ~14% (~0.7s) A payment-gateway status check firing on every checkout load; it only needs to run occasionally
Page-builder rendering ~22% (~1.1s) Theme + page builder assembling the checkout form

The API call was the first clean win: a read-only status check, safe to cache briefly. Shipped immediately for ~0.2s. Small, free, zero-risk.

Based on the profile, I told the client the remaining plugin audit would be worth "a few hundred milliseconds, not a miracle." I put that expectation in writing. Keep that sentence in mind.

The twist: the optimizer was the bottleneck

The client greenlit a controlled plugin test on staging. Method: deactivate one suspect, measure checkout 3x, reactivate, measure again (A/B/A), so a hosting hiccup can't masquerade as a result.

  • Suspect #1 (a checkout-flow plugin): no measurable difference. Deactivating it would have been a guess dressed as a fix.
  • Suspect #2: WP-Optimize - checkout went from 4.6-4.7s to 1.68-1.73s. Minus 60%, reproducible across all three A/B/A rounds, with the payment form still working.

Why would a performance plugin cost 3 seconds? Its page-cache layer still runs its checking/processing logic on pages that can never be cached - cart and checkout are dynamic by definition. So on exactly the pages that were hurting, it contributed pure overhead. The site also had a second caching plugin for the same job, so the two overlapped.

I had to go back to the client and say my written estimate of "a few hundred milliseconds" was wrong by an order of magnitude. Being wrong in that direction is pleasant, but the lesson is the same as with OPcache: the profile tells you where to dig, only the controlled test tells you what's true.

Production results after shipping both fixes: server response time went from 3.3s to 2.35s on the live checkout (the remaining gap vs staging is the structural cost below). The client tested it live and released the milestone the same morning.

What's still slow (the honest part)

The remaining ~2s is not a bug. It's WooCommerce + a page-builder-heavy theme + a normal-sized plugin stack, all initializing on every request, on shared hosting where Redis isn't available and PHP workers are limited. That gets better with structural choices - a leaner theme, fewer always-on plugins, or hosting where object caching actually exists - not with another patch. If your host doesn't offer Redis at all (as here), that's not something any plugin can fix. A managed WordPress host like Cloudways gives you Redis + OPcache out of the box - I spun up a WooCommerce store on it and measured 0.6-0.7s TTFB on cached pages, ~0.9s on the uncacheable cart page, and Lighthouse mobile 99, from the other side of the Pacific (affiliate link, disclosure below).

There's no "install this plugin and get 2 seconds." If someone tells you there is, ask for the before/after numbers, not the promise. Sometimes the numbers will surprise you - this time the 2 seconds came from uninstalling one.

Takeaways

  • A theme-swap test is good evidence, not a diagnosis. It tells you where to look, not what's there.
  • Say the wrong hypothesis out loud, then check it anyway. Twice, in this case - OPcache (wrong villain) and "a few hundred ms" (wrong ceiling).
  • Performance plugins are plugins. They have per-request overhead like everything else, and on uncacheable pages a page cache is all cost, no benefit. Two caching plugins doing one job is a smell.
  • A/B once is an anecdote; A/B/A three times with a working payment form is a result you can ship.
  • Ship the small safe win immediately. Scope the structural conversation separately - and honestly.

Disclosure: the Cloudways link above is an affiliate link. I only link to it because it solves the exact hosting limitation described in this post, and I tested it myself before recommending it.

Top comments (0)