Het filteren van een enorme WooCommerce-catalogus hoeft je server niet te laten crashen. Door traditionele AJAX-filters te vervangen door een frontend-first JSON-index, zijn we erin geslaagd om meer dan 50.000 WooCommerce-producten te filteren in minder dan 5ms. Hier is de exacte technische analyse van waarom AJAX faalt op schaal, waarom database-tuning niet genoeg is, en hoe client-side filtering het probleem van grote catalogi definitief oplost.
Waarom worden WooCommerce-filters traag bij 50.000 producten?
Wanneer je WooCommerce-webshop groeit voorbij de 10.000 producten, beginnen traditionele filter-plugins hun zwaktes te tonen. Bij 50.000 producten storten ze vaak volledig in. Je merkt misschien dat het klikken op een simpel “Kleur: Zwart” filter plotseling 3 tot 5 seconden duurt om te laden. Tijdens piekmomenten met veel verkeer, zoals Black Friday, veranderen die vertragingen van 5 seconden in 504 Gateway Timeouts, waardoor je shop onbereikbaar wordt op het moment dat het er het meest toe doet.
Veel webshopeigenaren geven in eerste instantie hun hosting de schuld. Ze upgraden naar een grotere VPS, wijzen meer PHP-workers toe of installeren Redis object caching. Hoewel deze upgrades misschien een paar honderd milliseconden van de laadtijd afschaven, lossen ze het onderliggende probleem niet op. Het probleem is niet de hardware van je server; het is de architecturale limiet van hoe WordPress gegevens opvraagt. Onze gids over waar WooCommerce-filters je site vertragen legt de volledige waterval uit, maar hier focussen we specifiek op wat er breekt bij 50.000+ producten.
De schaalbaarheid van een database-gedreven systeem is altijd afhankelijk van de complexiteit van de queries. Bij een kleine shop met 500 producten is een SQL-query razendsnel. Maar naarmate het aantal producten toeneemt, groeit de database-index, en daarmee ook de tijd die nodig is om die index te doorzoeken. Voeg daar de complexiteit van variabele producten en talloze attributen aan toe, en je hebt een recept voor performance-problemen die niet simpelweg met meer CPU-kracht op te lossen zijn.
Waarom is AJAX-filtering zo traag op grote WooCommerce-catalogi?
Bijna elke populaire WooCommerce-filter-plugin op de markt maakt gebruik van een AJAX-architectuur. De workflow ziet er als volgt uit:
- Een klant klikt op een filter (bijv. “Maat: Large”).
- De browser stuurt een HTTP-verzoek naar
admin-ajax.phpof een aangepast REST API-endpoint. - De server start de WordPress-core op, inclusief WooCommerce en alle actieve plugins.
- De filter-plugin voert een database-query uit om alle “Large” producten te vinden.
- De plugin voert tientallen extra queries uit om de resterende facet-tellingen te berekenen (bijv. uitzoeken dat er nu nog 14 “Blauwe” producten en 0 “Rode” producten beschikbaar zijn in “Maat: Large”).
- De server rendert het nieuwe HTML-grid en stuurt dit terug naar de browser.
Bij 500 producten duurt dit proces misschien 400ms. Bij 50.000 producten moet de database honderdduizenden rijen scannen. De facet-telling alleen al (stap 5) wordt een exponentieel wiskundig probleem dat MySQL op de knieën dwingt. Elke extra filteroptie die je in de zijbalk toont, voegt extra berekeningen toe aan de serverlast.
Vermenigvuldig dat met het aantal gelijktijdige shoppers. Tien mensen die tegelijkertijd filteren, betekenen tien volledige WordPress-opstartcycli, tien sets zware SQL-JOINs en tien HTML-re-renders — die allemaal strijden om dezelfde PHP-workerpool als je afrekenproces en winkelmandje. Dit is de reden waarom het bladeren door categorieën je checkout plat kan leggen tijdens uitverkopen, zelfs als het aantal bestellingen op dat moment nog beheersbaar is. Het is een inefficiënt gebruik van serverbronnen voor een taak die ook elders uitgevoerd kan worden.
Vergelijk dit met AJAX vs frontend-first filtering architecturen — het cruciale verschil is waar het werk gebeurt: op de server of in de browser van de gebruiker.
Hoe vertraagt wp_postmeta de WooCommerce-filtering?
WooCommerce slaat niet elk attribuut op in een eigen, nette kolom. Filter-plugins moeten een mix van taxonomietabellen en geserialiseerde meta-data doorzoeken — en die mix is precies waarom AJAX-filters bezwijken bij 50.000 producten. De manier waarop WordPress data structureert is geoptimaliseerd voor flexibiliteit, niet voor high-performance filtering op schaal.
Globale attributen (bijv. Kleur met slug pa_color) slaan hun waarden op als taxonomietermen: “zwart” leeft in wp_terms, gekoppeld aan producten via wp_term_taxonomy en wp_term_relationships. Dit vereist complexe JOINs in SQL om de juiste producten te vinden.
Lokale (aangepaste) attributen op een product worden gebundeld in één enkele wp_postmeta rij: _product_attributes. Die waarde is een geserialiseerde PHP-array — geen afzonderlijke geïndexeerde rijen. Voorbeeld van de structuur in de database:
a:1:{s:9:"materiaal";a:6:{s:4:"name";s:9:"Materiaal";s:5:"value";s:15:"Katoen | Linnen";s:8:"position";i:0;s:10:"is_visible";i:1;s:12:"is_variation";i:0;s:11:"is_taxonomy";i:0;}}
Wanneer PHP die string leest, wordt het iets als materiaal → naam: Materiaal, waarde: Katoen | Linnen. MySQL kan niet efficiënt filteren binnenin die blob; de server moet de data laden en “unserializen” (omzetten naar een leesbare array) voordat hij ermee kan werken. Dit is een enorm intensief proces voor de CPU van je server, zeker als het voor duizenden producten tegelijk moet gebeuren.
Variaties voegen nog een extra laag toe: gekozen waarden staan in aparte wp_postmeta sleutels per variatie, bijv. attribute_pa_color = zwart. Voor een product met 20 variaties betekent dit 20 extra rijen in de meta-tabel die doorzocht moeten worden.
Wanneer een shopper filtert op Kleur + Materiaal + Prijs, moet de plugin wp_posts, taxonomietabellen en variatie-meta-sleutels aan elkaar koppelen (JOINen), en soms zelfs _product_attributes parsen. De facet-telling herhaalt dit werk voor elke optie in de zijbalk. Bij 50.000 SKU’s hamert dit patroon bij elke klik op de database. Lees waarom wp_postmeta en taxonomy JOINs WooCommerce-filters laten crashen voor de volledige technische diepgang.
Hoe filter je 50.000 WooCommerce-producten zonder serverbelasting?
Als het bevragen van de database de flessenhals is, is de enige logische oplossing om te stoppen met het bevragen van de database. Dit is de kernfilosofie achter frontend-first filtering. In plaats van de server te dwingen om bij elke klik zware berekeningen uit te voeren, verplaatsen we de werklast naar de plek waar de gebruiker zich al bevindt: de browser.
Moderne smartphones en laptops hebben ongelooflijk krachtige processors — meer dan in staat om een dataset van 50.000 items in milliseconden te filteren. Door gebruik te maken van de rekenkracht van de client, ontlasten we de server volledig. Hier is hoe InstantFilter dit aanpakt:
1. Het Codebook (Hydratatie)
Wanneer je InstantFilter installeert, scant het je WooCommerce-catalogus en genereert het een hooggecomprimeerd JSON “codebook”. Dit codebook bevat een gemapte index van al je producten, categorieën, attributen en prijzen. Het is geen lijst met HTML-elementen; het is ruwe, geminimaliseerde data die specifiek is gestructureerd voor razendsnelle verwerking.
Wanneer een gebruiker je categoriepagina bezoekt, wordt dit JSON-bestand op de achtergrond gedownload, samen met de initiële HTML. Omdat het een statisch bestand is, wordt het direct geserveerd vanuit het RAM-geheugen van je server of via je CDN (Content Delivery Network). Dit betekent dat de server nauwelijks werk hoeft te verrichten om de data bij de klant te krijgen.
2. Nul Serverbelasting bij interactie
Zodra het JSON-codebook in het geheugen van de browser is geladen, zit de taak van de server erop voor wat betreft het filteren. Wanneer de klant klikt op “Kleur: Zwart”, wordt er geen AJAX-verzoek verstuurd. De JavaScript-engine van de browser berekent onmiddellijk de doorsnede van de arrays in de JSON-data om de overeenkomende producten te vinden en de facet-tellingen te herberekenen.
3. Sub-5ms Executie
Omdat het berekenen van array-doorsnedes in JavaScript extreem snel is, duurt de filterlogica tussen de 1,5ms en 5ms, zelfs bij 50.000 producten. Het productgrid wordt onmiddellijk bijgewerkt. Er zijn geen laad-icoontjes, geen grijze schermen en absoluut nul impact op de CPU van je server. De gebruikerservaring is vloeiend en direct, wat cruciaal is voor de conversie in je webshop.
InstantFilter rendert nog steeds het initiële productgrid als server-side HTML. Dit is essentieel voor SEO; crawlers van zoekmachines en social media previews zien een normale WooCommerce-categoriepagina. Het JSON-codebook verbetert de gebruikersinterface (UI) na het laden; het vervangt geen SEO-vriendelijke markup door een lege JavaScript-shell. Je behoudt dus alle voordelen van een snelle interface zonder in te leveren op vindbaarheid.
Kan betere hosting AJAX-filters sneller maken bij 50.000 producten?
Het korte antwoord: nee — althans niet op een manier die schaalbaar is. Upgraden van gedeelde hosting naar een dedicated VPS, het toevoegen van Redis object cache of het optimaliseren van MySQL-indexen kan honderden milliseconden van individuele queries afschaven. Dat helpt bij 2.000 producten. Maar bij 50.000 producten blijft de wiskunde tegen je werken: facet-tellingen, variatie-meta en taxonomietabellen moeten bij elke klik opnieuw worden berekend.
Er zijn “geïndexeerde” AJAX-plugins die een aparte index-tabel opbouwen in plaats van ruwe JOINs uit te voeren bij elk verzoek. Deze zijn sneller dan standaard AJAX-filters, maar ze maken nog steeds bij elke interactie contact met de server. Je betaalt nog steeds de prijs van netwerkvertraging (latency), het opstarten van PHP en de strijd om serverbronnen. Frontend-first filtering verwijdert deze terugkerende kosten volledig na de eenmalige download van het codebook.
| Aanpak | Serverlast per filterklik | Typische vertraging bij 50K producten | Schaalt met aantal shoppers |
|---|---|---|---|
| Standaard AJAX (wp_postmeta JOINs) | Hoog — volledige WP boot + SQL | 2–8 seconden | Nee — workers raken snel op |
| Geïndexeerde AJAX (aparte index-tabel) | Gemiddeld — nog steeds PHP per klik | 400ms–2s | Gedeeltelijk — betere queries, zelfde architectuur |
| Frontend-first JSON (InstantFilter) | Nul na hydratatie | 1,5–5ms (client-side) | Ja — filtering draait op elk apparaat |
Voor een diepere vergelijking van plugin-architecturen kun je onze vergelijkingsgids voor WooCommerce-filter-plugins raadplegen. Hierin leggen we uit waarom de keuze voor een architectuur belangrijker is dan de keuze voor een hostingpakket.
Werkt frontend-filtering wel als het JSON-bestand groot is?
In software-engineering bestaan er geen wondermiddelen, alleen afwegingen (trade-offs). De afweging voor 0ms filtering is dat de browser de JSON-index moet downloaden bij de eerste keer dat de pagina wordt geladen. Is dat een probleem voor de laadtijd?
Dankzij agressieve compressie blijft de voetafdruk van de data klein in verhouding tot de grootte van de catalogus. Een shop met 10.000 producten verstuurt doorgaans een ge-gzipped JSON-bestand van ongeveer 40KB tot 80KB — dat is kleiner dan een enkele geoptimaliseerde afbeelding. Zelfs bij 50.000 producten blijft de payload meestal ruim onder de 300KB (afhankelijk van het aantal attributen, categorieën en prijsranges). Dit is een verwaarloosbare hoeveelheid data op moderne internetverbindingen.
Bovendien wordt deze eenmalige download gecached door de browser voor volgende bezoeken. Klanten die meerdere categorieën bekijken in één sessie, hoeven de volledige index niet opnieuw te downloaden, tenzij de producten veranderen. Je CDN of paginacache kan het statische JSON-bestand ook serveren vanaf locaties dicht bij de gebruiker (Edge), waardoor de Time to First Byte (TTFB) wereldwijd laag blijft.
Wanneer moet je overstappen van AJAX naar frontend-first filtering?
Er is geen universele grens, maar deze signalen betekenen meestal dat AJAX zijn houdbaarheid heeft overschreden voor jouw shop:
- Filterklikken duren consequent langer dan 1 seconde op een testomgeving met een realistische catalogusgrootte.
- Je ziet PHP-worker limieten of 504-fouten optreden tijdens het browsen — niet alleen bij het afrekenen.
- Je hebt Redis toegevoegd, betere hosting gekocht of database-indexen geoptimaliseerd, maar de vertraging is nauwelijks verbeterd.
- Je catalogus is groter dan ~5.000 producten met meerdere attributen en variaties.
- Het bouncepercentage op mobiel schiet omhoog op gefilterde categoriepagina’s (zie onze gids over mobiele filtervertraging).
De veiligste weg is om je productieomgeving te klonen naar een staging-omgeving, InstantFilter naast je huidige plugin te installeren en de vertraging te meten met de DevTools van je browser. Wissel nooit zomaar van plugin op je live site zonder een back-up en een plan om terug te kunnen draaien — onze documentatie over probleemoplossing behandelt controles voor caching en staging.
De beloning is een shop die voor altijd razendsnel filtert na die ene download — geen draaiende wieltjes meer, geen PHP-workers die verspild worden aan complexe berekeningen. Je checkout-flow behoudt volledige toegang tot de serverbronnen omdat het browsen door de catalogus niet langer strijdt om dezelfde PHP-pool. Dit zorgt voor een stabielere shop, zelfs tijdens de drukste verkoopdagen van het jaar.
Test altijd eerst op staging voordat je live gaat; raadpleeg onze documentatie voor compatibiliteit met verschillende caching-oplossingen.
Op zoek naar een alternatief voor FacetWP dat gebouwd is voor schaalbaarheid? Bekijk InstantFilter vs FacetWP of bekijk de prijzen van InstantFilter voor onze Founders-plannen en de proefperiode van 14 dagen.
Blijf ontdekken
Het filteren van een grote catalogus is een architecturale beslissing, geen hosting-upgrade. Volg deze paden voor meer informatie:
- Waar WooCommerce-filters je site vertragen
- AJAX vs frontend-first filtering
- InstantFilter vs FacetWP
- Trage filters oplossen: wp_postmeta uitgelegd
- InstantFilter prijzen