If you search for "WooCommerce slow" right now, most of the results will tell you to install a caching plugin, optimise your images, and upgrade your hosting plan. Those are not wrong exactly, but they address the symptoms rather than the cause in most cases. A store that is genuinely slow usually has a database problem, and you cannot cache your way out of a database problem.
This is what we actually look at when a client brings us a slow WooCommerce store. Some of it is technical. All of it is specific. None of it involves installing another plugin and hoping for the best.
If you want someone to handle this for you, our MySQL database optimization service covers exactly this kind of audit and targeted fix for WooCommerce stores.
Start With the Slow Query Log, Not PageSpeed
PageSpeed Insights will tell you your Time to First Byte is slow. It will not tell you which MySQL query is causing it. The slow query log will.
If you have access to your server, enable the slow query log in MySQL by adding these lines to your MySQL configuration file:
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
This logs every query that takes more than one second. Let the store run for a few hours with real traffic and then look at the log. Sort by query time or by frequency. The queries that appear at the top of both lists are your targets.
If you do not have direct server access, most managed hosting control panels expose a slow query log somewhere. If yours does not, that is a reason to consider different hosting — but more on that later.
The Four Most Common WooCommerce Database Problems
1. The wp_options autoload problem
WordPress loads every autoloaded row from wp_options on every page request. This starts small and grows quietly. Plugins add rows to wp_options with autoload set to yes, and they rarely clean them up when they are deactivated or deleted. A store that has had a dozen plugins come and go over three years might have several megabytes of autoloaded data being read on every single request.
Check what you have with this query:
SELECT SUM(LENGTH(option_value)) as autoload_size
FROM wp_options
WHERE autoload = 'yes';
Anything above 800kb is worth investigating. Run this to see the largest individual entries:
SELECT option_name, LENGTH(option_value) as size
FROM wp_options
WHERE autoload = 'yes'
ORDER BY size DESC
LIMIT 20;
Most of what you find will be from plugins that are no longer active. Those are safe to delete. Options that belong to active plugins can usually have their autoload value changed to no if they are not needed on every page load. Do this carefully and test after each change.
2. Missing indexes on custom meta queries
WooCommerce uses post meta extensively. Product attributes, pricing, stock status, and custom fields all live in the wp_postmeta table. When you query products by a custom field — which WooCommerce does constantly — MySQL needs to find those rows efficiently.
The wp_postmeta table has indexes on meta_key and post_id by default, but if you are querying by meta_value as well, you may be running full table scans on a table with hundreds of thousands of rows. Check the EXPLAIN output of your slow queries. If you see "type: ALL" or "Extra: Using where" without a key reference, you are probably missing an index.
3. WooCommerce order table bloat
A store that has been running for a few years accumulates a lot of order data. The wp_posts and wp_postmeta tables hold WooCommerce order records, and they grow continuously. WooCommerce has a built-in tool to archive orders and clean up old data, but it is often not configured or used.
Beyond archiving, WooCommerce 8.2 and later uses custom tables for orders (HPOS — High Performance Order Storage). If you are still on the legacy post-based order storage on an older store, migrating to HPOS is one of the highest-impact performance changes you can make for a high-order-volume store. Query times for order lists and order reports improve dramatically.
4. Product attribute queries without proper caching
Variable products with many attributes generate expensive database queries when loading the product page. WooCommerce builds the variation data dynamically and this can involve multiple joins across the attribute and term tables. If you have products with 10 or more attribute combinations, you will see this show up in the slow query log.
The correct fix here is to ensure object caching is configured. WordPress's built-in caching API is a transient layer that uses the database by default. Connecting it to Redis or Memcached means these expensive variation queries are cached in memory and only run when the cache expires rather than on every product page load.
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_TIMEOUT', 1);
define('WP_REDIS_READ_TIMEOUT', 1);
define('WP_REDIS_DATABASE', 0);
What Caching Actually Fixes (and What It Does Not)
Page caching, which tools like WP Rocket and LiteSpeed Cache provide, works by serving pre-built HTML files instead of running WordPress and its database queries on every request. This is very effective for static or semi-static pages like your homepage, category pages, and product pages for simple products.
Page caching does not help with:
- The checkout page, which must be dynamic and cannot be cached
- Cart updates and product availability checks
- Order confirmation pages
- Any page that varies by logged-in user
- Admin-side order processing
If your store is slow primarily at checkout, page caching will make no difference. The checkout is slow because of the database queries that run during checkout. Those need to be fixed, not cached.
Hosting Does Matter, But Not in the Way Most Guides Imply
Shared hosting will cause problems for any store with meaningful traffic. That is true. But moving to a better server without fixing the underlying database issues will make the site faster by a smaller amount than expected, and the same problems will reappear as the store grows.
What matters most in your hosting for WooCommerc performance is MySQL configuration. Specifically, the innodb_buffer_pool_size setting determines how much of your database can be held in memory. A value that is too small means MySQL reads from disk constantly. A value appropriate for your database size can make a dramatic difference to query times without changing a single line of application code.
For most WooCommerce stores on a VPS, setting innodb_buffer_pool_size to 60 to 70 percent of available RAM is a reasonable starting point. Your hosting provider may handle this configuration for you or may give you access to modify it.
A Practical Checklist
- Enable the slow query log and identify your top 10 slowest queries
- Check your wp_options autoload size and clean up orphaned entries
- Review EXPLAIN output on slow queries and add missing indexes where identified
- Enable Redis or Memcached for WordPress object caching
- If on WooCommerce 8.2 or later, migrate to HPOS order storage if not already using it
- Configure page caching for public pages but exclude cart, checkout, and account pages
- Review innodb_buffer_pool_size on your MySQL configuration
If you have worked through this list and need a more thorough investigation, our WooCommerce store development team can audit your store, identify the specific bottlenecks, and implement fixes with measurable before and after results.
Most WooCommerce stores that come to us with performance complaints see the biggest improvement from items one through four on that list. The fixes are targeted and measurable. You can run a query before and after and see the difference directly.
If you have worked through the list and the store is still slow, the problem is usually in custom code or a specific plugin that is making poorly structured database calls. That requires looking at the slow query log output and tracing back which part of the application is generating each query. It is more involved but it is findable.

