A slow store costs sales. Visitors leave product pages that take seconds to appear, and every extra second in checkout gives a buyer time to change their mind. WooCommerce can be very fast, but a typical store collects plugins, tracking scripts and years of data that slow it down. This guide works through the usual causes in the order that gives the most improvement for the least risk.
1. Measure before changing anythingLink to this section
Find out what is slow:
- Server time (TTFB). If the HTML takes over 600 ms to arrive, the problem is PHP, the database or missing caching. Check in the browser's Network tab or with
curl -w "%{time_starttransfer}\n" -o /dev/null -s URL. - Front-end weight. If HTML arrives quickly but the page renders slowly, look at images, scripts and fonts with PageSpeed Insights and the Core Web Vitals guide.
- Specific plugins. The free Query Monitor plugin shows queries, slow hooks and HTTP calls per page, grouped by plugin. It's the quickest way to find the plugin that adds 400 ms to every request.
Test the important journeys: home, a category, a product, add to cart, cart, checkout, and the admin order list. Write down the numbers so you can prove each change helped.
2. Control cart fragmentsLink to this section
To keep the mini cart in the header up to date on cached pages, WooCommerce can run a wc-ajax=get_refreshed_fragments request. On stores whose theme relies on it, that request runs on page loads and is never cached, so every visitor triggers PHP and database work even on otherwise cached pages.
Recent WooCommerce versions load the fragments script only where it's needed, and block themes use the Mini-Cart block instead. On classic themes that still enqueue it everywhere, limit it:
add_action( 'wp_enqueue_scripts', function () {
if ( is_admin() ) {
return;
}
$needs_fragments = is_cart() || is_checkout() || is_product() || ( WC()->cart && ! WC()->cart->is_empty() );
if ( ! $needs_fragments ) {
wp_dequeue_script( 'wc-cart-fragments' );
}
}, 20 );Test afterwards: add to cart from a category page, then check the header count updates. If your theme's mini cart depends on fragments everywhere, adjust where the condition allows them rather than removing them blindly.
3. Enable HPOSLink to this section
High-Performance Order Storage moves orders from the generic wp_posts/wp_postmeta tables into dedicated order tables with proper indexes. Order searches, admin lists and reports get much faster on stores with many orders, and checkout writes less data.
New stores use it by default. For older stores (WooCommerce → Settings → Advanced → Features):
- Check every plugin that touches orders declares HPOS compatibility; WooCommerce lists incompatible ones.
- Enable compatibility mode so both storages stay in sync, and let the background sync finish.
- Switch to HPOS as the authoritative storage, test orders, refunds and integrations, then turn off sync once you're confident.
Custom code must use the CRUD API (wc_get_order(), $order->get_meta()) rather than get_post_meta() on orders. The WooCommerce customisation guide covers this in detail. Do it on staging first and take a backup.
4. Cache what can be cachedLink to this section
Most of a store's traffic lands on pages that are the same for every anonymous visitor: home, categories, products and content. Full-page caching for these gives the biggest single speed-up. The rules that keep it safe:
- Bypass for cart, checkout, my account and any request with the
woocommerce_items_in_cartorwp_woocommerce_session_cookies, and for logged-in users. - Purge product pages when price or stock changes; good host caches and plugins do this automatically.
- Add a persistent object cache (Redis) for everything that can't be page-cached: carts, checkout, logged-in customers and the admin.
The caching guide has the Nginx rules and explains each layer.
5. Trim plugins and scriptsLink to this section
Every plugin can add PHP work, database queries and front-end assets. Review them:
- Remove plugins that aren't used, and ones that duplicate each other (two SEO plugins, three analytics tools).
- Load assets only where needed. Payment gateway scripts belong on checkout, not on blog posts. Many plugins enqueue globally; dequeue them on pages that don't need them.
- Audit tracking tags. Marketing pixels and chat widgets are often the heaviest scripts on the page. Load them through a tag manager with consent, and delay non-essential ones until after interaction.
- Avoid page builders on product templates where possible; they add heavy markup to every product.
6. Product imagesLink to this section
Product and category pages are image-heavy:
- Upload sensibly sized originals (around 2,000 pixels for zoomable images), in WebP where your setup supports it. The image to WebP converter is handy for one-off uploads such as banners.
- Make sure category grids use the thumbnail sizes, not full images, and that
sizesmatches the grid. - Don't lazy-load the main product image; it's usually the LCP element.
- Galleries and zoom scripts should load the large image only on interaction.
The responsive images guide covers srcset, sizes and priorities in depth.
7. Database housekeepingLink to this section
Large stores accumulate data that slows queries:
- Expired sessions and transients. WooCommerce cleans sessions on a schedule; if WP-Cron doesn't run reliably, they pile up. On busy sites, disable the page-load trigger and run WP-Cron from a real server cron every minute or five; the cron expression builder helps write the schedule.
- Action Scheduler. WooCommerce's background job tables (
wp_actionscheduler_*) can grow to millions of rows from completed and failed actions. Check for failures under Tools → Scheduled Actions, fix their cause, and let retention clean old ones. - Autoloaded options. Options marked autoload are loaded on every request. Plugins sometimes autoload large values. Find the biggest with a query on
wp_optionsand switch large, rarely used ones to not autoload. - Post revisions and orphaned meta from old plugins. Clean with care, and only after a backup.
-- The largest autoloaded options
SELECT option_name, LENGTH(option_value) AS bytes
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto')
ORDER BY bytes DESC
LIMIT 20;8. A faster checkoutLink to this section
Checkout speed affects conversions directly:
- Use the Checkout block where your payment and shipping plugins support it; it's lighter and faster than many legacy customisations.
- Remove fields you don't need. Fewer fields means faster completion.
- Watch remote calls. Shipping rate APIs, address validation, fraud checks and tax services all run during checkout. Query Monitor's HTTP panel shows their timing; cache rates where the provider allows, and set short timeouts.
- Keep payment scripts lean. Load only the gateways you offer.
- Test real orders on staging after changes, with each payment method, and check order emails and integrations. Webhook payloads sent to other systems can be checked with the JSON formatter.
9. HostingLink to this section
Software tuning only goes so far. A store needs current PHP (8.2 or newer), OPcache, enough PHP workers for concurrent checkouts, Redis, and a database with enough memory. If TTFB is still high on uncached pages after the steps above, the hosting is likely the limit.
A one-week plan for a slow storeLink to this section
If you're facing a slow store and don't know where to start, this order works well and keeps risk low:
- Day 1: Measure. Record TTFB and Core Web Vitals for home, category, product, cart and checkout. Install Query Monitor on staging and note the slowest plugins and queries.
- Day 2: Quick wins. Update PHP, enable OPcache, remove unused plugins and fix any obviously oversized images on the home and category pages.
- Day 3: Caching. Add or correct page-cache bypass rules for cart, checkout and account; add Redis object caching. Test cart and checkout as a guest and as a customer.
- Day 4: Front end. Limit cart fragments, dequeue plugin assets where they aren't needed, and delay non-essential third-party scripts.
- Day 5: Database and orders. Clean up Action Scheduler failures, check autoloaded options, set up a real server cron, and plan the HPOS switch if it's not already on.
- Day 6: Checkout. Review fields, payment scripts and remote calls; consider the Checkout block if your extensions support it.
- Day 7: Re-measure and document. Compare against Day 1, write down what changed and why, and set up monitoring so regressions are noticed.
Every change goes to staging first, with a backup and a real test order, before production. The aim isn't a perfect PageSpeed score; it's a store that loads quickly for real customers and lets them pay without waiting.
Keeping it fastLink to this section
Speed slowly decays as plugins, scripts and products are added. Re-check the key pages after every major plugin install or theme change, and review the plugin list every few months. A short checklist kept with the store's documentation makes this a routine task, not an emergency.
Common problemsLink to this section
- Fast in tests, slow for customers. Tests hit cached pages; customers with items in their cart bypass the cache. Test with a cart.
- Mini cart count wrong after caching. Fragments removed where the theme needs them, or a cached page served to a visitor with items in the cart.
- Admin order list slow. HPOS not enabled, or a plugin adds expensive columns. Check with Query Monitor.
- Checkout spinner hangs. A remote API or a slow
woocommerce_checkout_*hook. Check HTTP calls and PHP error logs. - Database keeps growing. Action Scheduler or session clean-up isn't running because WP-Cron is unreliable.
Frequently asked questionsLink to this section
How many plugins is too many?Link to this section
There's no fixed number. One badly written plugin can do more damage than twenty good ones. Measure plugins individually with Query Monitor.
Will a CDN fix a slow store?Link to this section
It speeds up images, scripts and cached pages, but not uncached cart and checkout requests. Those depend on PHP, the database and remote calls.
Is HPOS safe to enable?Link to this section
Yes, once your plugins are compatible. Use compatibility mode during the switch, test on staging, and keep a backup.
Should I switch to a headless storefront for speed?Link to this section
Usually not first. A well-tuned WooCommerce store is fast enough for most businesses. Headless makes sense for specific needs, and adds complexity; see the headless guide if you're considering it.
Want your store profiled and sped up? Tell me about it.
Test yourself
3 quick questions on this lesson.
Finished this lesson?
Mark it complete to track your progress through the learning paths.