Une agence cliente nous a contactés parce que leur site WordPress vitrine flagship avait un TTFB (Time To First Byte) de 800ms. Le client final commençait à râler. Lighthouse score : 42/100 en performance. Inacceptable pour un site de communication.
On a divisé ce TTFB par 5 en 2 heures, sans toucher au code applicatif. Voici comment.
Le diagnostic
Premier réflexe : profiler. On a installé un script qui mesure chaque étape entre la requête entrante et la réponse sortante :
Nginx receive : 2 ms
Nginx → PHP-FPM : 140 ms ← !!
PHP-FPM bootstrap : 220 ms ← !!
WordPress init : 80 ms
MySQL queries (×47) : 290 ms
WordPress render : 60 ms
Nginx send : 8 ms
────────────────────────────
Total TTFB : 800 ms
Trois bouchons identifiés : la communication Nginx ↔ PHP-FPM (140ms — anormal), le bootstrap PHP-FPM (220ms — anormal aussi), et 47 requêtes MySQL (le code applicatif, on n’y touche pas).
Intervention 1 — PHP-FPM en socket Unix
L’instance précédente faisait passer Nginx → PHP-FPM en TCP sur localhost. Ça marche, mais ça force le kernel à passer par la pile réseau pour chaque requête, même en local. Bascule en socket Unix :
# /etc/php/8.2/fpm/pool.d/site.conf
listen = /run/php/site.sock
listen.owner = www-data
listen.group = www-data
# /etc/nginx/sites-available/site
fastcgi_pass unix:/run/php/site.sock;
Gain immédiat : 140ms → 6ms sur cette étape.
Intervention 2 — OPcache + JIT
Le bootstrap de 220ms vient du fait que PHP recompile les fichiers à chaque requête. OPcache cache le bytecode, JIT compile les hotspots en code natif. La config par défaut de PHP 8.2 désactive ces optimisations.
; /etc/php/8.2/fpm/conf.d/10-opcache.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.jit_buffer_size=128M
opcache.jit=tracing
Gain : 220ms → 18ms sur le bootstrap.
Intervention 3 — MySQL query cache + index
Sur les 290ms de requêtes, on en a récupéré 130ms en activant le query cache MySQL et en ajoutant 3 index manquants sur les tables wp_options et wp_postmeta. Les index, c’est en limite avec “toucher au code”, mais c’est une opération admin DB côté infra, donc on s’autorise.
Le résultat
Nginx receive : 2 ms
Nginx → PHP-FPM : 6 ms ✓
PHP-FPM bootstrap : 18 ms ✓
WordPress init : 80 ms
MySQL queries (×47) : 160 ms ✓
WordPress render : 60 ms
Nginx send : 8 ms
────────────────────────────
Total TTFB : 140 ms ✓
De 800ms à 140ms. Lighthouse score passé de 42 à 89. Aucune ligne de code applicatif modifiée. Temps total d’intervention : 1h47.
Pourquoi c’est rare chez nous
Ces trois optimisations sont notre configuration par défaut. Elles sont appliquées sur tous les sites qu’on héberge, dès le provisionning. Le client en question avait migré depuis un autre hébergeur sans qu’on touche à sa config — par erreur de notre part. On a ajouté un check dans notre process de migration pour que ça ne se reproduise pas.
Note — L’optimisation infra est incluse dans tous nos forfaits. Si votre site rame, on regarde — sans frais additionnels.