WooCommerce performance optimization comes down to a short list of layers: the server (response time, PHP version, PHP workers), caching (page cache, object cache, browser cache), asset delivery (images, CDN, scripts) and the store’s own data (database tables, scheduled jobs, plugins). If your WooCommerce store is slow, one or two of those layers is almost always the cause, and fixing the right one makes a far bigger difference than working through a generic checklist.
The catch is that product pages, cart, checkout and the WordPress admin often have separate bottlenecks. So I start every audit by working out which part of the store is slow, then fix causes in order of impact. This guide follows the same path: how to diagnose a slow WooCommerce site, the 12 causes I find most often with the fix for each, a speed audit checklist, and which fix to do first.
How to diagnose a slow WooCommerce site
Find out which pages are slow before you change anything. A store where every page crawls has a server or caching problem. A store where only checkout drags has a session, gateway or query problem. Test logged out in a private window with the cache warm, since an admin session bypasses page caching.
| What is slow? | Likely causes | First checks |
|---|---|---|
| Every page | Hosting limits, high TTFB, no full-page cache, heavy theme | Server response time, cache headers, hosting logs |
| Product and category pages | Large images, variations, filters, third-party scripts | Waterfall test, image weight, plugin assets |
| Cart and checkout only | Sessions, payment gateways, AJAX, database queries | Query Monitor, Network tab, gateway scripts |
| WordPress admin only | Database bloat, Action Scheduler backlog, WP-Cron | Scheduled Actions screen, slow-query logs |
| Mobile only | Heavy JavaScript, fonts, LCP image, tracking tags | PageSpeed Insights plus a real device |
| Only at traffic peaks | PHP workers, database saturation, uncached dynamic requests | Hosting resource charts, concurrency test |
Then work down these questions and stop at the first yes:
- Is the homepage also slow? Then the problem is foundational: hosting, TTFB, page cache, theme assets or images. Start at cause 1.
- Are cart and checkout noticeably slower than product pages? Look at sessions, payment gateway scripts, AJAX requests, database queries and cache exclusions (causes 4, 6 and 7).
- Are product or category pages slow only with large catalogues or active filters? The problem is product queries, faceted filters, search and object caching (causes 5 and 10).
- Is only the WordPress admin slow? Customers are probably fine. Check database bloat, Action Scheduler backlogs and WP-Cron (causes 6 and 11).
This takes about ten minutes and stops you optimising images for a week when the real problem is a slow server. Your tools for the rest of this guide are PageSpeed Insights, the Network and Coverage panels in Chrome DevTools, and Query Monitor on a staging copy of the store.
1. Slow hosting, PHP workers or high server response time
Hosting sets the ceiling for everything else. If the server takes 800ms to generate a page, that delay is baked into every response, and no image compression or script deferral can remove it. WooCommerce does far more work per request than a brochure site, so budget shared hosting shows its limits quickly, especially during sales and campaigns.

How to confirm it: check Time to First Byte in PageSpeed Insights or the DevTools Network tab. Google’s web.dev guidance treats 0.8 seconds or less as a good TTFB; on a cached WooCommerce page I aim for under 200ms. If everything feels uniformly sluggish, admin included, and your hosting dashboard shows PHP workers or CPU at their ceiling during peaks, the server is the bottleneck.
The fix: look for a plan with:
- PHP 8.2 or 8.3, since WooCommerce runs measurably faster on newer PHP versions
- Server-level caching (Nginx FastCGI cache or LiteSpeed LSCACHE) that handles cart and checkout exclusions
- Redis or Memcached available as an object cache backend
- Enough PHP workers for your peak traffic, plus daily backups and a staging environment
Kinsta, WP Engine and Cloudways (often the best value at mid-scale) all have good WooCommerce track records, and a well-configured LiteSpeed VPS gives high-volume stores more control. Buying optimisation plugins to compensate for a weak server does not work, because plugins add work to every request and only better hosting adds capacity. If your host says resources are fine but TTFB stays high, the cause is usually slow application-level queries, which need profiling.
2. Oversized product images (WebP, compression and lazy loading)
Oversized product images are the most common cause of slow product and category pages, and the easiest to fix. A 3000 pixel photograph displayed in a 600 pixel slot makes every visitor download several times the data they need. On mobile that is often the difference between a fast product page and an abandoned one.
How to confirm it: in the DevTools Network tab, filter by images and sort by size. Anything over a few hundred kilobytes on a product page deserves attention, and PageSpeed will often flag the main product photo as the Largest Contentful Paint (LCP) element.
The fix: resize images to the largest size they are actually displayed at, then convert them to WebP. Google’s figures put lossy WebP at 25–34% smaller than comparable JPEGs at the same quality. ShortPixel and Imagify both bulk-convert existing media libraries, serve WebP automatically and work with WooCommerce product galleries without extra setup. For product photography, lossy compression at 80–85% quality is usually indistinguishable to the eye; apply it to gallery images and category thumbnails too.
WordPress has added loading="lazy" to images by default since version 5.5, which helps shop archives most. Confirm your theme has not disabled it. The one exception is the LCP image, usually the main product photo above the fold: lazy loading it delays the very image the page is measured on. Load it immediately and add fetchpriority="high" if the browser needs a hint. My guide to optimizing WordPress for Core Web Vitals covers the LCP, CLS and INP targets in more depth.
3. Missing or misconfigured page cache
Without a full-page cache, WooCommerce rebuilds every page in PHP on every request and reruns the same database queries. Serving pre-generated HTML instead is usually the single biggest improvement available to a slow store. The symptom is high TTFB on pages that should be static, and a site that copes with one visitor but falls over with fifty.
How to confirm it: load a page twice in a private window and compare response times, or inspect the response headers for a cache hit indicator. Many hosts expose an x-cache style header showing HIT or MISS.
The fix: use host-level page caching if your host offers it, and a caching plugin if not. WP Rocket and LiteSpeed Cache are the two strongest options for WooCommerce and both exclude cart, checkout and account pages automatically. LiteSpeed Cache needs a LiteSpeed web server for its full feature set. W3 Total Cache is a capable free alternative but needs those exclusions configured by hand. I compared all three in WP Rocket vs W3 Total Cache vs LiteSpeed Cache.
Both plugins also set browser cache headers; on a VPS, check your Nginx or Apache config is not overriding them. If caching is on but the hit rate stays low, cookies or query strings are usually fragmenting the cache.
4. Cart and checkout cached like normal pages
This cause costs orders, which matters far more than milliseconds. Cart, checkout and account pages are personal to each visitor, and caching them can serve one customer a page built from another customer’s session. Most caching plugins exclude these pages by default, but aggressive plugin settings and CDN rules routinely override that.
How to confirm it: customers report wrong cart contents, totals that do not update, coupons that fail, or another person’s details. In a private window, add a product and check that the cart count and totals update correctly.
The fix: WooCommerce’s caching configuration docs list what must stay dynamic: the Cart, Checkout and My Account pages, plus the session cookies woocommerce_cart_hash, woocommerce_items_in_cart and wp_woocommerce_session_. Exclude those URLs and bypass the cache whenever a cart cookie is present. Set the exclusions at both the plugin and the CDN, because a CDN rule can quietly override a plugin setting.
Never cache everything to chase a PageSpeed score: a broken checkout loses orders for hours before anyone notices. If checkout is already misbehaving, my WooCommerce checkout troubleshooting guide covers the wider set of causes. Any time live orders are affected, bring in a developer.
5. No persistent object cache (Redis)
A persistent object cache such as Redis stores database query results in memory, so WordPress skips identical work on the next request. WooCommerce reads product meta, stock levels, pricing rules, related products and session data on almost every page, so Redis helps it more than a content site, especially on cart, account and logged-in pages that cannot be page cached.
How to confirm it: run Query Monitor on staging and look at the query count and total query time per page. Several hundred queries on a product page suggests object caching would help. On a small catalogue it may change very little, so measure before paying for an add-on.
The fix: Kinsta, WP Engine and Cloudways all offer Redis, sometimes as a paid add-on, and many hosts include it unused. Enable it on the server, install the Redis Object Cache plugin by Till Krüss, and check that its dashboard shows Connected. A hosting panel claiming Redis is on while the drop-in is not loaded is common. No WooCommerce-specific configuration is needed.
If Redis is connected and queries stay slow, a plugin is usually generating uncacheable queries on every request.
6. Database bloat, expired transients and Action Scheduler backlogs
WooCommerce writes a lot of data: orders, sessions, transients, product revisions and scheduled background jobs. Over a few years those tables grow large enough to slow routine queries. The usual symptom is a slow WordPress admin with an acceptable storefront, order screens that take seconds to load, and scheduled emails or stock syncs that arrive late.
How to confirm it: open WooCommerce, then Status, then Scheduled Actions, and check the completed, pending and failed counts. Tens of thousands of completed actions means pruning is falling behind. Check the transient count with wp transient list --search="wc_*" --format=count (WP-CLI docs), watch the size of the wp_woocommerce_sessions table, and ask your host for slow-query logs.
The fix: take a full database backup first. Then:
- Delete expired transients with
wp transient delete --expired - Cap product revisions by adding
define( 'WP_POST_REVISIONS', 3 );to wp-config.php (wp-config reference) - Prune completed and failed scheduled actions, and adjust the Action Scheduler retention period so the backlog does not return
- Clear session rows if WooCommerce’s own cleanup cron has fallen behind on a high-traffic store
- Look for oversized autoloaded options in
wp_options, often left behind by plugins removed years ago
On a recent WooCommerce version, also confirm High-Performance Order Storage (HPOS) is enabled. It moves orders out of the posts tables into dedicated, indexed tables built for ecommerce queries, and has been the default for new installs since WooCommerce 8.2. WP-Optimize can automate monthly cleanup. Get a developer involved before bulk deletion on a store with real order history, or before switching an older store with legacy extensions to HPOS. The WordPress maintenance guide shows where this fits in a care routine.
7. Cart fragments and slow add to cart AJAX requests
Cart fragments slow a WooCommerce store when the wc-cart-fragments script fires uncached AJAX requests on pages that have no cart on them. Each request goes all the way to PHP. This is also a common reason for “WooCommerce add to cart slow” complaints, because every add to cart triggers a fragment refresh that waits on the server.
According to WooCommerce’s developer blog, since WooCommerce 7.8 the script is only enqueued when the Cart widget is rendered, when another script lists it as a dependency, or when code enqueues it. Some themes, Storefront included, hard-code the widget, so many stores still load it everywhere.
How to confirm it: open DevTools, filter the Network tab by Fetch/XHR, and reload a product or landing page. Look for get_refreshed_fragments requests on pages where nothing cart-related is shown, and note how long each one takes. A slow response usually points back to hosting or a missing object cache (causes 1 and 5).
The fix: WooCommerce’s recommended long-term fix is to replace the legacy mini-cart widget with the Mini-Cart block, which does not use cart fragments. Short of that, the same post gives this snippet to stop the script running outside WooCommerce pages (the file still loads, but it will not execute):
add_filter( 'woocommerce_get_script_data', function( $script_data, $handle ) {
if ( 'wc-cart-fragments' === $handle ) {
if ( is_woocommerce() || is_cart() || is_checkout() ) {
return $script_data;
}
return null;
}
return $script_data;
}, 10, 2 );
Do not disable cart fragments globally because a blog post said to. If your header shows a mini-cart on every page and you use page caching, the cart count can stop updating on cached pages. Test cart count updates, mini-cart behaviour and logged-in flows after every change. On the UK fashion store rebuild, cart fragments firing on every page load were defeating full-page caching on every product view.
8. Too many plugins, or plugins loading assets everywhere
Plugin behaviour matters more than plugin count. Ten well-built plugins can be lighter than three that load their CSS and JavaScript on every page. A booking form plugin loading its assets on all 400 product pages is a common and fixable problem, and every active plugin still adds PHP execution to each uncached request.
How to confirm it: use the Coverage panel in Chrome DevTools to see how much loaded CSS and JavaScript is unused on a product page. Query Monitor attributes slow queries to specific plugins. On staging, deactivate plugins one at a time and retest.
The fix: delete plugins you no longer use, including deactivated ones that are still installed. Remove duplicates, such as two caching or two SEO plugins. Homepage sliders and carousels are frequent LCP bottlenecks, so replace them with a static image section if the design allows. For plugins you need on specific pages only, load their assets conditionally; WooCommerce’s own performance best practices ask extension developers to do exactly that. Conditional loading usually needs code. For a short list of plugins worth their weight, see the best WooCommerce plugins for 2025.
9. Heavy theme, page builder, or unused CSS and JavaScript
A theme or page builder that wraps every product in nested layers and ships a large asset bundle sets a ceiling you cannot optimise past. The signs are render-blocking resources dominating your PageSpeed report, a page that looks complete long before it responds, and large CSS and JavaScript files coming from the theme or builder.

How to confirm it: check the Coverage panel for unused CSS, look at which files sit in the render-blocking list, and compare against a default theme on staging to see how much weight is the theme’s.
The fix: lightweight WooCommerce-compatible themes such as GeneratePress, Astra and Kadence handle product galleries, cart widgets and checkout styling without the bloat. Avoid themes bundling sliders, multiple page builder integrations or automatic Google Font loading. On an existing build, WP Rocket and LiteSpeed Cache handle minification, so you do not need a separate plugin like Autoptimize. Work through these settings one at a time:
- Minify CSS. Be careful with JavaScript minification: WooCommerce’s caching docs advise avoiding it with WP Rocket.
- Combine files only after testing checkout, since combining can break payment gateway scripts.
- Defer non-critical JavaScript, and exclude WooCommerce’s cart and checkout scripts from deferral.
- Remove unused CSS, and review pages that load conditional styles.
- Host fonts locally and preload the one font your above-the-fold content needs.
Payment gateway scripts (Stripe, PayPal, WooPayments) break most often after these changes, so place a test order each time. When you have done all of this and still fail Core Web Vitals, a lighter custom theme is usually cheaper than continuing to fight the current one.
10. Slow filters, search, variations and third-party scripts
Faceted filters, product search and variable products with many combinations generate expensive database queries that page caching rarely helps, because each filter combination is a unique request. Add chat widgets, analytics and advertising pixels, and the page waits on several third parties before it settles. Category pages that are fast until someone applies a filter point here.
How to confirm it: apply a filter and compare the response time with the unfiltered page, then use Query Monitor to see the queries the filtered request runs. In the Network tab, sort by domain to total up time spent on third-party scripts, and test with those tags blocked to see the difference.
The fix: remove tracking scripts nobody reads reports from (there is usually at least one), load chat widgets after the visitor interacts, and move large-catalogue search to an index-based solution so it stops querying the products table directly. Filters that are slow because of the product query structure need query-level development work.
11. WP-Cron, imports and badly timed background jobs
WordPress runs scheduled tasks on page loads by default, so a customer’s visit can trigger your stock sync. Add product imports, feed generation and backups running during trading hours, and the store competes with itself for server resources. The symptom is a store that slows at predictable times, or randomly for individual visitors.
How to confirm it: check whether WP-Cron still runs on page loads, review the Scheduled Actions screen for a growing backlog, and ask your host when its backup window is. My guide to WP-Cron not running correctly covers the diagnostics.
The fix: set up a real server cron job that calls wp-cron.php at a fixed interval, then add define( 'DISABLE_WP_CRON', true ); to wp-config.php, as described in the WordPress cron handbook. Move imports, feed builds and backups to your quietest hours. Never disable WP-Cron without the server cron in place: scheduled emails, subscription renewals and stock syncs stop silently.
12. No CDN for static assets
A CDN serves CSS, JavaScript, images and fonts from servers close to each visitor, which cuts the latency part of load time. For WooCommerce stores with international customers it also moves most static requests off your origin server, which matters during traffic spikes. Without one, every visitor fetches every file from a single location.
The fix: pick the CDN that matches your setup:
- Cloudflare’s free tier covers most small and medium stores, with static asset caching and DDoS protection. Configure its integration in WP Rocket or LiteSpeed Cache to avoid cache-purge conflicts when products change.
- Bunny.net uses pay-per-use pricing with no monthly minimum and has a simple WordPress plugin.
- Amazon CloudFront suits stores already on AWS or Cloudways.
WP Rocket and LiteSpeed Cache both rewrite asset URLs to your CDN domain. Repeat the cart and checkout exclusions from cause 4 at the CDN.
WooCommerce speed audit checklist
This WooCommerce speed audit checklist runs the cheap, safe checks before anything that can break an order. Work through it in order, record your numbers before changing anything, and retest after each fix. Most stores find their main bottleneck in the first four steps, and those steps need no code at all.
- Test logged out, in a private window, with the cache warm, and record load time and Core Web Vitals.
- Measure TTFB on a cached page. If it is high, start with hosting.
- Confirm page caching is active and that cart, checkout and my-account are excluded at the plugin and CDN.
- Check your largest product images against their displayed size, and confirm the LCP image is not lazy loaded.
- Run Query Monitor on a product page and on checkout, and note the query count and slowest queries.
- Check the Scheduled Actions screen for a backlog, and confirm WP-Cron runs from a server cron job.
- Filter the Network tab by XHR and look for cart fragment requests on pages with no cart.
- Use the Coverage panel to find unused CSS and JavaScript, and identify which plugin or theme ships it.
- Sort the waterfall by domain and total up third-party script time.
- After every change, retest cart updates, coupons, a test order and logged-in pricing.
The last step matters most: the work is only finished once the part that takes money still works.
Which WooCommerce speed fix should you do first?
Do the high-impact, low-risk fixes first: hosting or TTFB if the server is the bottleneck, page caching with correct cart and checkout exclusions, and resizing oversized product images. For most stores these three account for the majority of the available improvement. Riskier changes to scripts and cart behaviour come later, with checkout testing after each one.
Next, with a staging site and a backup in place: database and Action Scheduler cleanup, the plugin audit with conditional asset loading, Redis if your query counts justify it, and a CDN. After that, carefully and with full checkout testing: cart fragments, AJAX behaviour, script deferral and minification. These produce real gains, and they are also where stores break.
Leave the last few PageSpeed points until the end; with a four-second checkout, 90 versus 95 is the wrong number to chase. Once speed stops being the constraint, the WooCommerce conversion optimization guide covers checkout UX, express payments and cart recovery.
When to hire a WooCommerce performance developer
Hire a WooCommerce performance developer when revenue is exposed or the cause is code. Configuration work is fine to do yourself: resizing images, enabling caching, clearing transients with a backup, removing unused plugins and moving backups off peak. Checkout bugs, conditional asset loading, query-level changes and large-store cleanups carry enough risk to justify paying for experience.
Also get help when Query Monitor shows slow queries you cannot attribute, or the store is still slow after every cause above. My test: if the change you are about to make could stop an order completing and you are not certain you would notice, stop.
For a sense of what the work looks like, the UK fashion store case study took a plugin-heavy store from 6.1s to 1.4s mobile load time in three weeks without touching the design. The work combined Redis, a rebuilt image pipeline, deferred third-party scripts, cart fragments limited to cart and checkout, and a database cleanup that accounted for roughly a third of the improvement. If your store is stuck, send me the URL and the pages that feel slow, and I will tell you which layer the problem is in. You can read more about my WordPress speed optimization service and WooCommerce development work.


