The Pattern
The store feels fine when you browse top-level categories. The moment you stack filters, everything gets expensive.
- color + size + brand + price
- out-of-stock exclusion
- sort by popularity
- AJAX refresh on every click
On small catalogs that is manageable. On 5,000 products and up, bad filtering architecture turns archive pages into query storms.
If your WooCommerce filters get slower every time merchandising adds another attribute, here is where I look first.
Why Filtering Gets Slow
Most slow filter setups are doing one or more of these:
- querying
postmetafor data that should live in taxonomies or lookup tables - calculating filter counts on every request with no cache strategy
- joining variation data in ways MySQL cannot optimize well
- sorting by custom meta keys on already heavy filtered queries
- loading oversized product loops, then asking JavaScript to hide what SQL should have filtered
WooCommerce can scale further than people think, but only if the data model matches the query shape.
Fix 1: Stop Using meta_query for Everything
If "color", "brand", "material", or "size" is stored in custom meta, filtering will stay expensive. Those values belong in attributes or taxonomies so WordPress can use indexed term relationships instead of brute-force meta scans.
Bad pattern:
$query->set('meta_query', [
[
'key' => 'brand',
'value' => 'nike',
],
[
'key' => 'color',
'value' => 'black',
],
]);
Better pattern:
$query->set('tax_query', [
'relation' => 'AND',
[
'taxonomy' => 'pa_brand',
'field' => 'slug',
'terms' => ['nike'],
],
[
'taxonomy' => 'pa_color',
'field' => 'slug',
'terms' => ['black'],
],
]);
That one change is often the difference between a 300 ms filter and a 4 second one.
Fix 2: Use WooCommerce's Lookup Tables
WooCommerce has already done a lot of work here. The product attributes lookup table exists for a reason. If you are still filtering against raw post meta when the platform has lookup data ready, you are paying a penalty you do not need to pay.
In current WooCommerce builds, check:
- product attributes lookup is enabled
- lookup regeneration has completed after imports
- the table is fresh after large catalog updates
If imports run nightly and the lookup table lags behind, users will see incorrect counts or missing products. Slow filtering and wrong filtering often come from the same stale lookup state.
Fix 3: Count Calculation Needs Strategy
The visible product list is only part of the cost. Filter counts are the real killer on large stores.
If every request has to compute:
- how many black shirts remain
- how many medium shirts remain
- how many Adidas shirts remain
after every active filter combination, the database gets hit from multiple directions at once.
This is where I usually add:
- cached count fragments by tax state
- aggressive object caching
- fewer visible filter groups per template
- selective AJAX refresh instead of rebuilding the whole sidebar every time
Facet-heavy stores without Redis or Memcached are usually harder to tune because the site has no stable place to hold those repeated count calculations.
Fix 4: Watch Sorting
Filtering plus orderby=meta_value_num is where a lot of stores go to die.
Examples:
- sort by custom priority score
- sort by dynamic margin
- sort by a plugin-written meta field
If that meta column is not indexed in a way the query can use efficiently, MySQL ends up sorting a large intermediate result set after already doing heavy filter work.
My default advice is:
- keep the default sort simple
- move fancy merchandising logic to category-level curation where possible
- precompute sortable values into native WooCommerce lookup fields if the business really needs them
Fix 5: Reduce Query Churn in the Theme
I still find stores where the theme makes filtering worse by:
- running extra
WP_Queryinstances inside archive templates - calculating badges and stock messaging with per-product queries
- fetching variations for every product card
- loading recommendation widgets before the primary archive is done
The filter query can be reasonable and the page still feels slow because the template turns each result row into more database work.
Query Monitor helps here. Check the slow queries, but also count how many queries the archive page runs in total. If filtering one page causes 250+ queries, you have a template problem as well as a catalog problem.
What I Change on Real Stores
On large-catalog WooCommerce work, the fix is usually some mix of:
- move filterable values into taxonomies or native attributes
- enable and repair lookup tables
- add object caching
- trim filter groups on high-volume archives
- remove meta-based sorting from default category pages
- simplify archive templates
If the store also has checkout or cart performance issues, my WooCommerce mini cart AJAX fix and HPOS custom queries guide cover two other places where custom code usually falls behind the platform.
The Rule
The bigger the catalog gets, the less forgiving WooCommerce becomes about data modeling mistakes.
If your filters are built on attributes, lookup tables, cache, and lean templates, large catalogs stay manageable. If everything lives in post meta and the theme asks the database twenty follow-up questions per product card, the archive page will feel slow forever.
Need a Store Performance Pass?
I optimize WooCommerce stores at the database, caching, template, and infrastructure layers, not just with plugin toggles. If your category pages drag once customers start filtering, let's fix the stack.
