În plin Black Friday(Da, Black Friday începuse deja. Calendarul încă nu fusese informat), un magazin WooCommerce avea toți cei 160 de workeri PHP blocați și pagini care se încărcau în 35–47 de secunde. După ajustarea decisivă a regulilor de purge din LiteSpeed Cache, workerii ocupați au scăzut la 17–30, iar paginile au coborât la ~2 secunde, fără hardware nou.
Problema
Comenzile veneau la 20–30 de secunde una de alta, iar serverul nu mai făcea față. Checkout-ul răspundea atât de greu încât clienții apăsau din nou pe butonul de comandă. Așa au apărut comenzi duplicate în „Plată în așteptare”: același client, aceeași sumă, de două sau trei ori.
Serverul: VPS într-un container cu 16 vCPU și 32 GB RAM, LiteSpeed cu lsphp 8.2, MariaDB, Redis ca object cache… ar trebui să zboare cu aceste resurse.
Diagnosticul pas cu pas
Din terminalul WHM, în timp ce magazinul primea comenzi. Am verificat raport litespeed, numar de procese, strace-uri, redis… Pe scurt: multe ferestre negre cu text alb și două creiere care începeau să aibă nevoie de răcire suplimentară.

Primele verificări arătau spre Redis. Redis sufocat: 160 de procese PHP care regenerau pagini ce ar fi trebuit să vină din cache.
Optimizările făcute înainte de soluția finală
Buffer pool MariaDB: de la 128 MiB la 4 GiB
Am mărit buffer pool-ul InnoDB din MariaDB de la 128 MiB la 4 GiB, pe un server cu 32 GiB RAM și o bază de date de aproximativ 8 GiB. Modificarea s-a aplicat dinamic, fără restart. În eșantioanele măsurate ulterior, citirile din fișierele de date InnoDB au scăzut de la aproximativ 2.000/s la 21/s, iar 99,93% dintre citirile logice au fost servite din buffer pool. Comparația reflectă și traficul și încălzirea cache-ului din acele intervale.
Optimizarea a îmbunătățit eficiența bazei de date, dar nu a eliminat blocajul: toți cei 160 de workeri PHP rămâneau ocupați, cu aproximativ 187–221 de cereri la coadă. MariaDB respira mai ușor. Noi încă nu.
Plugin-uri, cron și restartul PHP
Am redus și activitatea auxiliară: am dezactivat plugin-uri neesențiale și am înlocuit apelul HTTP al cron-ului cu execuție locală prin PHP 8.2, la fiecare cinci minute, cu flock pentru prevenirea suprapunerilor(lipsa acesteia devenise o problema între timp). Aceste intervenții nu au golit coada PHP. Existența unor joburi de sincronizare restante nu dovedea că un singur plugin ocupa toți workerii.
Restartul workerilor PHP a oferit doar o ameliorare temporară: Pentru câteva clipe am avut senzația că am rezolvat. Apoi s-au întors toți cei 160 și coada de după grrr…
Două fundături
Oprirea object cache-ului
Cu object cache-ul oprit, mai multă muncă a ajuns în MariaDB. Inițial, debitul PHP a crescut, dar CPU-ul a ajuns aproape de 100%, au apărut răspunsuri HTTP 500, iar serverul a repornit. Am încheiat proba și am reactivat Redis.
Renice
Bla bla …. alti termeni tehnici … Sistemul nu permite să crești prioritatea lui Redis, așa că am scăzut-o pe a proceselor PHP cu renice -n 10. Redis a coborât de la 38 ms la 5–9 ms, iar cererile PHP terminate s-au dublat. Odată deblocat Redis, însă, procesorul a ajuns la 6–10% liber, iar load-ul a urcat la 62. O pază pusă dinainte a făcut automat graceful restart la LiteSpeed – pentru a nu ajunge iar la un reboot…
Concluzia: problema era că prea multe cereri ajungeau la PHP, nu ordinea în care primeau procesorul.
Cauza reală: cache-ul golit la fiecare comandă
Multe vânzări înseamnă coș, checkout și pagină de mulțumire, care nu se pot pune în cache. Am împărțit ~1 570 de cereri dinamice din log-ul de acces:
| Tip de cerere | Procent | Se poate servi din cache? |
|---|---|---|
| Prima pagină, categorii, produse | 58% | Da |
| Coș, checkout, plată, mulțumire | 18% | Nu |
get_refreshed_fragments | 10% | Se poate reduce |
| Admin, AJAX, API | 9% | Parțial |
| Căutare | 4% | Nu |
Cererile către coș, checkout, plată și pagina de mulțumire reprezentau aproximativ 18% din numărul cererilor dinamice analizate. Cele 58% către prima pagină, categorii și produse arătau însă un potențial important de reducere a muncii PHP prin cache pentru vizitatorii anonimi eligibili. Procentele sunt rotunjite.
În LiteSpeed Cache, la orice actualizare de produs, inclusiv o schimbare de stoc după o comandă, erau bifate pentru golire automată toate paginile, prima pagină, pagina de articole, toate categoriile și arhivele. Cu o comandă la 20–30 de secunde, cache-ul era golit încontinuu, iar cererile care ratau cache-ul ajungeau să dureze 35–47 s, inclusiv așteptarea la coadă. Aceași pagină servită din cache fusese măsurată la 0,018 s.

Soluția: era simplă setările schimbate în LiteSpeed Cache
Sigur că era o bifă. După ce o găsești, orice problemă pare simplă. În cele din urmă era o setare simplă cum de nu ne-am gândit la ea de la început… wp-admin → LiteSpeed Cache → Cache.
- Tab-ul Purge → Auto Purge Rules For Publish/Update: debifate All pages, Front page, Home page, Pages, Author archive, Post type archive, Yearly, Monthly și Daily archive, Term archive. „Serve Stale” a rămas pornit.
- Tab-ul WooCommerce → Product Update Interval: „Purge product only when the stock status changes. Do not purge categories on changes to the quantity or stock status.”
Compromisul: prima pagină și categoriile pot afișa temporar informații de stoc vechi. TTL-ul de 30 de minute nu garantează actualizarea afișării în cel mult 30 de minute: Opțiunea aleasă pentru WooCommerce invalidează pagina produsului la schimbarea statutului de stoc, nu la fiecare modificare de cantitate; cantitatea exactă afișată poate rămâne veche. Checkout-ul rămâne dinamic și verifică disponibilitatea la plasarea comenzii.
Rezultate
Măsurători la 1–2 minute după salvare, cu trafic mai mare decât înainte (88–163 de cereri/s față de 61–76). Comparația surprinde etapa finală a intervenției, după optimizările anterioare; în fazele precedente, coada PHP ajunsese și la peste 200 de cereri. Timpii paginilor de mai jos sunt timpi de răspuns și includ eventuala așteptare la coadă.
| Indicator | Înainte | După |
|---|---|---|
| Workeri PHP ocupați (din 160) | 84–160 | 17–30 |
| Cereri PHP la coadă | până la 61 | 0 |
| Cereri PHP terminate pe secundă | 4–6 | 9–12 |
| Timp de răspuns Redis | 34–38 ms | 0,33 ms |
| Prima pagină | 35–47 s | 2,2 s |
| Categoria Black Friday | peste 40 s | 2,3 s |
| Checkout | 5 s | 0,47 s |
| Load (1 min) | 10–12, vârfuri de 62 | ~11, stabil |
Cu paginile servite din nou rapid, numărul de comenzi intrate a crescut vizibil imediat după schimbare.
Redis s-a vindecat singur: cu ~25 de procese PHP active în loc de 160, nu mai stătea la coadă după procesor. Lecția: când un server WooCommerce cade sub comenzi, întâi verifică dacă paginile care pot fi servite din cache chiar sunt servite din cache.
Magazinul tău WooCommerce încetinește când vin comenzile?
*Atenție! Setările de mai sus au funcționat pe acest server și pot diferi de la site la site. Înainte de orice modificare, asigură-te că ai un backup valid și nu apăsa „Purge All” în plin vârf de trafic.