Skip to content
Inte tillgänglig på svenskaEnglish
Get in touch

Most WooCommerce slowdowns come from five places

A slow WooCommerce store is rarely a mystery. Autoloaded options, scheduled tasks, order storage, heavy plugins and uncached pages explain most cases. How to find which one it is before changing anything.

When a WooCommerce store gets slow, the first suggestion is usually a bigger server or another caching plugin. Sometimes that helps for a week. Then the store is slow again, because the cause was never found.

The same five things explain most slow stores. None of them are exotic, and all of them can be measured before anything is changed. Measuring first matters, because the wrong fix costs money and often makes the next diagnosis harder.

Measure before you change anything

Install Query Monitor on a staging copy of the store, or on production if you can limit it to administrators. Load the pages that feel slow: the product page, the cart, checkout and the order list in the admin.

Query Monitor shows the number of database queries, the slowest ones, which plugin triggered them and how long PHP spent on the page. That is usually enough to point at one of the areas below.

Write the numbers down. Page generation time, query count and the slowest query for each page give you a baseline, and a way to prove that a fix did something.

1. Autoloaded options

WordPress stores settings in the wp_options table. Options marked as autoloaded are read into memory on every single request, whether the page needs them or not.

Plugins add options and rarely clean up after themselves. Over a few years a store can end up loading several megabytes of settings from removed plugins, expired caches and old logs on every page view, including requests from bots.

Since WordPress 6.6, options larger than 150 KB are not autoloaded unless a plugin explicitly asks for it, and Site Health flags a critical issue when autoloaded options exceed 800 KB in total. Existing options are not checked again until they are next saved, so an old store still carries its history.

What to look for:

  • The total size of autoloaded options. A few hundred kilobytes is normal, several megabytes is not.
  • Options belonging to plugins that are no longer installed.
  • Large serialized arrays that a plugin uses as a cache.

Removing an option a plugin still needs breaks that plugin, so check what each one is before deleting it. Switching autoload off for large options that are rarely used is often the safer first step.

2. Scheduled tasks that pile up

WooCommerce runs a lot of work in the background: emails, webhooks, stock updates, subscription renewals and cleanup jobs. It uses Action Scheduler for this, and many extensions use it too.

Two problems are common. The first is that WordPress only checks for due tasks when someone loads a page, as described in the WP-Cron documentation. The tasks then run in a separate background request, but they still compete with visitors for the same PHP workers and database. On a quiet store that means tasks run late. On a busy one, a long batch job can slow down the pages being served at the same time.

The second is a queue that never empties. A failing integration can leave hundreds of thousands of pending or failed actions in the database, and every new run has to work through those tables.

What to check:

  • Tools > Scheduled Actions in the admin. Look at the number of pending and failed actions and what they belong to.
  • Whether WP-Cron is triggered by real server cron instead of page loads. Setting DISABLE_WP_CRON and running cron every minute from the server makes tasks run on time. Heavy jobs still use server resources, so a long queue has to be fixed at its source.
  • Old completed actions. They are cleaned up automatically, but only if the cleanup itself gets to run.

3. How orders are stored

For most of WooCommerce's history, orders were stored as posts, with their details spread across the post meta table. Every order added many rows to a table shared with pages, products and everything else. Searching and filtering orders meant joining large tables, which gets slow as the store grows.

High-Performance Order Storage moves orders into dedicated tables. It has been the default for new stores since WooCommerce 8.2. Stores that started earlier are often still on the old storage, because switching requires every plugin that touches orders to be compatible.

If the order list in the admin is the slow part, or reports time out, check which storage the store uses under WooCommerce > Settings > Advanced > Features. The Features page links to a list of plugins that are not yet compatible, which tells you what has to be updated or replaced before switching.

4. One plugin doing too much

Query Monitor groups queries and time by component. Quite often a single plugin is responsible for most of the load. Typical cases:

  • A related products or upsell plugin that runs uncached queries across the whole catalogue on every product page.
  • A filter or search plugin that builds its index on the fly.
  • A plugin that calls an external API during page load, so the page waits for someone else's server.
  • Logging or statistics plugins writing to the database on every request.

The fix depends on the plugin. Sometimes a setting helps, sometimes an update, and sometimes the plugin has to be replaced by something that does less. Turning plugins off one by one on a staging copy and measuring again is slow but reliable.

5. Pages that are never cached

Product and category pages can usually be cached as full pages, which takes PHP and the database out of the picture for most visitors. Cart, checkout and account pages cannot, because they are different for every customer.

Problems appear when the rules are wrong in either direction:

  • A cookie or query string makes the cache treat every visit as unique, so nothing is ever served from cache.
  • A plugin starts a session for every visitor, which tells many caches to skip the page.
  • On older WooCommerce versions, or with themes that hard-code the classic mini-cart widget, the cart fragments script makes an uncached request on every page, even for visitors who never add anything.

Check the response headers of a product page in an incognito window. Most caches and hosts add a header that says whether the response was a hit or a miss. If it is always a miss, find out why before adding another caching layer on top.

When it is the server after all

After the five areas above are checked, some stores are simply too big for their hosting. Signs of that are slow responses even on cached pages, a database that is slow on simple queries, or PHP workers that are always busy at peak hours.

At that point a bigger plan, a dedicated database, object caching with Redis or Memcached, or a host that specialises in WooCommerce makes sense. Doing it in that order means the money goes to the actual bottleneck.

Fix one thing at a time

Change one thing, measure the same pages again and compare with the baseline. If several changes go in at once and the store gets faster, nobody knows which one helped. If it gets slower, nobody knows which one to roll back.

For most slow stores, finding the one or two places where time is lost, fixing those and moving background work off visitors' requests is enough. A rebuild is rarely the first thing to try.

Sources

  • WooCommerce
  • WordPress
  • performance
  • database
  • hosting

Keep reading

More articles

All articles