Een mail van de host dat PHP-workers vol zitten, gaat bij een grote WooCommerce-shop vaak over de filter en niet over de categoriepagina. Zolang elke klik een request is, bezet die klik een worker. Na hydratatie kost een filterklik van InstantFilter geen worker: er is geen request, dus geen PHP, en 0 SQL per klik.
Waarom raken WooCommerce-filters de PHP-workers op?
De host telt processen, niet paginabezoeken. Een categorie-URL die uit de paginacache komt, kost geen worker. De klik op een kleur wel, als die klik naar admin-ajax.php of een REST-route gaat. Die request bootst WordPress, houdt een worker vast tot de query klaar is, en geeft hem daarna vrij. Bij één bezoeker merk je dat als een spinner. Bij een sale merk je het als een grafiek waarin alle workers bezet zijn en nieuwe requests in de wachtrij vallen.
Zoek je op woocommerce filters exhausting php workers, dan is dit de mail. De host noemt een limiet, bijvoorbeeld een handvol workers op een klein pakket, en een piek die daarmee samenvalt. De piek valt samen met verkeer op archieven waar een filter staat, niet met verkeer op een statische pagina. De categorie zelf blijft 200 vanuit cache. De 502 of 504 zit op de filter-endpoint.
Meer workers kopen verhoogt het aantal gelijktijdige kliks dat je aankunt. Het verandert niet dat elke klik er een nodig heeft. Een catalogus van 10.000, 20.000 of 50.000 producten maakt elke worker langer bezet, omdat de query langer duurt. Langere bezetting maal meer kliks vult dezelfde pool sneller dan een kleine shop met dezelfde bezoekersaantallen.
Wat staat er in het slow query log als de workers vol zitten?
Het slow query log en de worker-grafiek horen bij elkaar. Een worker die een trage SELECT draait, komt niet vrij voor de volgende klik. In het log zie je joins op termtabellen, op wp_postmeta, of op wc_product_attributes_lookup. De lookup table maakt de attribuut-join korter. Ze maakt de worker niet overbodig. De request bestaat nog, en MySQL houdt die request bezig tot de telling klaar is.
woocommerce filter slow query log is de zin die een developer plakt naast de hostmail. Eén trage query van twee seconden is één worker twee seconden kwijt. Twintig van die queries tegelijk zijn twintig workers, of een wachtrij als de pool kleiner is. De timeout die de shopper ziet, is vaak de wachtrij plus de query, niet alleen de query. De browser geeft het op terwijl het verzoek nog in PHP staat.
Waarom helpt een timeout-verhoging niet bij gelijktijdige filterklikken?
Een hogere max_execution_time laat een trage query uitlopen in plaats van haar af te kappen. De worker blijft langer bezet. Bij gelijktijdige kliks wordt de pool daardoor slechter, niet beter. Een proxy-timeout van 60 seconden verbergt de 504 en laat de rij workers vollopen met requests die de shopper al heeft weggeklikt.
Hetzelfde geldt voor object cache rond de query. Als de plugin de uitkomst van een veelgebruikte combinatie bewaart, is de tweede identieke klik sneller. De eerste klik van elke unieke combinatie, en elke combinatie die niet in de cache zit, neemt nog een worker. Een shop met veel facetten heeft meer combinaties dan de cache warm houdt. Tijdens een sale zijn veel van die combinaties nieuw.
Hoeveel workers kost een filterklik na de eerste pageload?
Nul, als de klik de server niet meer raakt. InstantFilter rendert de eerste HTML op de server. Daarna zit het archief in het codebook in de browser. Een klik daarna bezet geen PHP-worker. Dat getal staat in de productiestandaard: 0 workers tijdens het filteren. Er is geen nieuwe meting in deze pagina. Er is geen request om te meten.
De eerste load kan wel een worker gebruiken, zoals elke ongecachede HTML-response. Die ene render is cachebaar. WP Rocket, LiteSpeed of Cloudflare mogen de categorie-URL bewaren. De klik erna zit niet in die cache en hoeft er ook niet in, omdat ze niet naar PHP gaat. De gids over filterperformance is de hub voor dat onderscheid. Deze pagina is de hostmail.
Andere plugins op dezelfde site kunnen nog steeds workers gebruiken: de winkelwagen, een betaalwebhook, een zoekbalk in de header. Die tellen niet als filterklik. Als het hostingpanel vol loopt op het moment dat mensen in de zijbalk klikken, en stil is op pagina’s zonder filter, wijst dat naar de filter-endpoint. Het Network-tabblad bevestigt het: een XHR per klik, of geen XHR per klik.
Wat antwoord je de host bij een grote catalogus?
De host ziet workers en queries. Jij ziet de architectuur. Zolang het filter een request per klik is, schaalt het aantal benodigde workers met het aantal gelijktijdige kliks, en de duur per worker met de catalogus. Een pakket met meer workers is een plafond. Het is geen andere architectuur. Bij 20.000 of 50.000 producten is dat plafond tijdens een actie alsnog krap, omdat elke query langer duurt.
Het antwoord dat de grafiek verandert: na de eerste load is er geen filter-request, dus de klikken tijdens de sale komen niet in de worker-pool. De pool blijft beschikbaar voor checkout en voor de eerste HTML van een ongecachede URL. Test dat op staging met de huidige plugin en daarna met InstantFilter, met hetzelfde aantal gelijktijdige kliks. Het slow query log hoort de tweede reeks niet te tonen.
Een index die de join versnelt maar de request laat staan, verlaagt de seconden per worker. Hij haalt de worker niet uit de grafiek. Dat zie je bij plugins die een eigen tabel hebben en toch admin-ajax.php aanroepen. De hostmail wordt dan “iets minder rood” in plaats van “de filterpiek is weg”. Voor een agency die een shop van tienduizenden producten beheert, is het verschil of de sale de pool vult.
Hoe lees je de hostmail naast het Network-tabblad?
Leg drie dingen naast elkaar. Het tijdstip in de hostmail. De URL die in het access-log het vaakst 502 of 504 geeft. De regel in het Network-tabblad op het moment dat je zelf een filter aanzet. Als het tijdstip samenvalt met verkeer op het archief, de fout-URL admin-ajax.php of een filter-route is, en jouw klik dezelfde URL raakt, dan is de worker-pool de optelsom van die kliks. Een trage homepage of een zware checkout heeft een andere URL in het log.
Tel daarna hoe lang één worker vastzit. De duur in het slow query log, plus de tijd die WordPress nodig heeft om te booten vóór de query, is de bezetting per klik. Deel de poolgrootte door die bezetting en je hebt een ruwe bovengrens voor gelijktijdige filteraars. Een shop met acht workers en een klik van één seconde houdt ongeveer acht gelijktijdige filteraars bij. De negende wacht. Tijdens een nieuwsbrief of een advertentie zit je daar zo overheen, ook als het daggemiddelde laag oogt.
Herhaal de telling nadat de filterklik de server niet meer raakt. De access-log hoort die action tijdens het filteren niet meer te laten groeien. De workers blijven dan vrij voor de requests die wél PHP nodig hebben. Dat is de controle die je terugstuurt naar de host: dezelfde piek in bezoekers, een andere regel in het log. Bewaar de twee screenshots, één van vóór de wissel en één van erna, zodat de mail een bijlage heeft in plaats van een indruk.
Ga verder
De hostmail hoort bij een request. Deze pagina’s laten zien waar die request vandaan komt.
- Waarom WooCommerce-filters traag worden
- Elke klik een request naar admin-ajax.php
- De lookup table haalt de worker niet weg
- Cache dekt de filterklik niet
- Prijzen en proefperiode