WooCommerce Speed Optimisation: Where Stores Lose Time (7 Fixes)
WooCommerce speed optimisation starts where shops differ from blogs: pages that can't be cached once a shopper has a basket, cart scripts, product image sizes, filter queries and years of order data. Fix those store-specific causes before generic speed tweaks.
WooCommerce's caching guide says to exclude the cart, checkout and My Account pages, plus cart and session cookies, so shoppers with a basket often get uncached pages.
Since WooCommerce 7.8, the cart fragments script loads only where a cart widget appears, but some themes hard-code that widget on every page.
WooCommerce's default product image sizes are 300 pixels wide for grids and 600 pixels for single product pages, and changing them needs a thumbnail regeneration.
High-Performance Order Storage moves orders into dedicated tables; it is the default for new stores since WooCommerce 8.2 but must be switched on for older ones.
A WooCommerce store can score well in a speed test and still feel slow to the people buying from it.
Most speed tests load your homepage once, with an empty basket. Real shoppers filter, open products and add to cart.
This guide covers the parts of a shop a blog never has. For the WordPress layer underneath, start with my guide on how to speed up WordPress.
Step 1: Test the Shopping Journey, Not the Homepage
Your homepage is the page shoppers spend least time on.
Test the pages that carry the sale instead.
Pick one URL for each:
A category page with plenty of products
A product page, ideally a variable product with several options
A filtered category page, with two filters applied
The cart and checkout, with something in the basket
Then test them twice: once in a fresh private window, and once after adding a product to the basket.
Why twice? WooCommerce's caching guide tells caching plugins to skip requests carrying cart and session cookies.
In practice, once you add something to the basket, many of your next pages are built fresh by the server.
So the empty-basket test shows your best case. The full-basket test shows what your buyers actually feel.
Pro tip: Time the slow moments by hand, too. Note how long "Add to basket" takes to respond, how long a filter takes to update and how long checkout takes to appear. Those waits lose sales even when the page scores look fine.
Step 2: Set Up Caching the Way WooCommerce Expects
Page caching still matters on a store.
It just needs rules a blog doesn't.
WooCommerce's caching documentation lists what to leave out of the cache:
Exclude
Why
Cart, Checkout and My Account pages
They show details specific to each shopper
woocommerce_cart_hash, woocommerce_items_in_cart and wp_woocommerce_session_ cookies
They mark visitors who have a basket or session
woocommerce_recently_viewed and store notice cookies
They change what each visitor sees
_wc_session_ in database caching
Session data has to stay current
Get these wrong and the symptoms are strange: baskets that empty themselves, one shopper's cart count showing to another, or a password reset that loops.
The docs name that last one as a sign the My Account page is being cached.
If you use another plugin, test your cart and checkout carefully after switching it on.
Geolocation. If you set WooCommerce → Settings → General → Default customer location to "Geolocate (with page caching support)", WooCommerce adds ?v= hash query strings to your URLs so location-specific pages can be cached, according to its MaxMind documentation.
If you don't need location-based pricing or tax on page load, plain "Geolocate" or a fixed default avoids those extra URLs.
Step 3: Stop Cart Fragments Running Where Nobody Needs Them
Cart fragments is the script that keeps a mini cart up to date without reloading the page.
It does that with extra background requests.
According to WooCommerce's post on cart fragments best practice, the script used to load on every page, even where no mini cart appeared. On busy stores, those requests could strain the server.
WooCommerce 7.8 changed that. The script now loads only when the classic cart widget appears, another script depends on it or it's added deliberately.
The catch is your theme.
The same post notes that some themes, Storefront among them, build the cart widget into their templates. Then the script still loads everywhere.
Here's how to check:
Open a product page with your browser's developer tools on the Network tab.
Filter requests for get_refreshed_fragments.
Browse two or three pages and see whether the request fires on each.
If it does, and your header mini cart is the only reason, look at the Mini-Cart block.
WooCommerce recommends it because it doesn't use the cart fragments API at all.
Don't simply block the script without a replacement. A basket count that never updates costs you more than a few milliseconds.
Step 4: Right-Size Product Images and Galleries
Category grids and product galleries are usually the heaviest parts of a store.
Most of that weight is images bigger than they need to be.
WooCommerce registers its own image sizes, separate from WordPress's. Its image size documentation gives the defaults:
Image size
Used for
Default
woocommerce_thumbnail
Product grids, such as category pages
300 px wide, cropped square
woocommerce_single
Main image on product pages
600 px wide, uncropped
woocommerce_gallery_thumbnail
Small images under the main one
100 x 100 px, square
Your theme may override these.
Check what it actually displays, then match the settings to it.
You'll find them under Appearance → Customize → WooCommerce → Product Images, unless your theme declares its own sizes.
After changing them, go to WooCommerce → Status → Tools and run Regenerate shop thumbnails.
Until you do, existing products keep their old files.
Then work on the uploads themselves:
Compress product photos before they go into the media library.
Keep the first gallery image eager. Lazy-loading the main product image delays the element shoppers look at first.
Watch gallery add-ons. Zoom, lightbox and 360-degree viewers often load their scripts on every product page, even for products with one photo.
Step 5: Keep Filters and Search From Overloading the Server
Filters are where store speed and SEO problems meet.
Every combination of colour, size, brand and price creates a new URL.
A page cache can't help with a URL nobody has requested before. So each new combination is built from scratch, often with heavy database queries behind it.
That's slow for shoppers. It's worse when crawlers follow every filter link, because your server spends its time building pages that will never sell anything.
Here's what I check on stores with filters:
How many filter URLs are linked. A crawl shows whether filter links are plain links crawlers can follow.
Which filter plugin builds them. Some plugins run far heavier queries than WooCommerce's own layered navigation.
Whether bots hit them. Server logs, or your host's traffic reports, show how much crawling lands on filtered URLs. My technical SEO checklist covers what else to look for in a crawl.
Search behaviour. Product search that scans every product description on each keystroke can lag badly on a big catalogue.
Step 6: Move Orders to HPOS and Clear Background Jobs
Older stores carry years of order data.
WooCommerce used to keep it in the same tables as your posts and pages.
High-Performance Order Storage changes that. According to WooCommerce's HPOS documentation, it stores orders in dedicated tables with their own indexes, which means fewer busy tables as order volume grows.
HPOS has been stable since WooCommerce 8.2 and is enabled by default on new installs.
Stores set up before that have to switch it on.
Here's the safe way to switch:
Go to WooCommerce → Settings → Advanced → Features.
Check for incompatible plugins. If any are active, WooCommerce disables the HPOS option and lists them.
Turn on compatibility mode, which keeps the old and new tables in sync.
Test orders, refunds, emails and any order extensions on staging.
Switch the authoritative storage once syncing has finished.
While you're in the back end, look at scheduled actions.
WooCommerce runs background jobs through Action Scheduler, and you can see them under Tools → Scheduled Actions or from WooCommerce's Status menu.
A long list of failed or overdue actions usually points to a plugin that keeps erroring, or background tasks that aren't running. Fix the cause before you clear the list.
Then clear the usual clutter WooCommerce's performance guide names: spam comments, old post revisions and expired transients. Back up first.
Step 7: Audit Checkout and Product Page Scripts
The last place stores lose time is the scripts that pile up on the money pages.
If you run a store, you've probably added a few of these yourself.
On a typical product page I find some mix of these:
Payment provider scripts for express checkout buttons
Review widgets and photo galleries from a reviews app
Tracking pixels for two or three ad platforms
Chat, upsell popups and "someone just bought this" notifications
Each one competes for the browser's attention when a shopper taps a size option or the "Add to basket" button.
That delay shows up in Interaction to Next Paint.
According to web.dev's guide to INP, a response of 200 milliseconds or less counts as good, and over 500 milliseconds counts as poor.
Work through the list with whoever owns each script:
Remove what nobody uses. Old pixels and abandoned apps are common.
Restrict the rest to the pages that need them. Express payment scripts rarely need to load on blog posts.
Then test the checkout as a shopper would, on a mid-range phone, with a real basket.
If the checkout is still slow with the scripts trimmed, the hosting is usually the limit. That's a conversation for a technical SEO review with your host's numbers in hand.
Speed Up the Pages That Take the Money
Don't start with the homepage.
Add a product to your basket today and time three things: the add-to-basket response, a filtered category page and the checkout. Those numbers tell you which step of this guide to tackle first.
And if you'd rather have someone find where your shop loses time, hosting and store speed are part of my WooCommerce SEO service. I test with a real basket, fix the caching rules and hand your developer a short list for the rest. You can see everything a WooCommerce store review covers before deciding.
Frequently asked questions
Why is my WooCommerce store slower than my WordPress blog?+–
A blog can serve almost every visitor a cached copy of each page. A store can't. Cart, checkout and account pages are personal to each shopper, cart scripts make extra requests and filters generate pages no cache has seen before. Product images and order data add weight too, so the same hosting that handles a blog can struggle with a shop.
Should I disable cart fragments in WooCommerce?+–
Only if nothing on your store needs it. Since WooCommerce 7.8 the script loads only where the classic cart widget appears, so many stores no longer run it everywhere. If your theme hard-codes a mini cart, removing the script can leave the basket count wrong. Switching to the Mini-Cart block, which doesn't use cart fragments, is the safer fix.
Is HPOS safe to enable on an existing WooCommerce store?+–
Usually, if your extensions support it. WooCommerce disables the option when an active plugin is incompatible, and offers a compatibility mode that keeps the old and new tables in sync while you test. Back up the database, enable sync on staging first and check orders, refunds and any order-related extensions before switching the live store.
What hosting does a WooCommerce store need?+–
Enough server capacity for the pages a cache can't serve: checkout, cart, account and filtered listings. Shared hosting that copes with a brochure site often slows down once real shoppers fill baskets at the same time. Look for a host that runs WooCommerce stores routinely, offers server-level page and object caching and can tell you its limits plainly.
Independent SEO consultant · 6+ years in SEO · 60+ client websites worked on
I'm an independent SEO consultant with 6+ years in SEO. I run audits, migrations and content programmes for businesses in Europe, the UK and the USA, and I build the automation behind my own research.