Mis à jour le 1er novembre 2026. Article réécrit pour PrestaShop 9.2 : profileur du back-office, caches natifs vérifiés dans le code, limitation des robots sur les facettes, partage des sessions entre nœuds et prévention des crashs. Il regroupe désormais nos articles sur le crash serveur PrestaShop, la montée en charge avec Nginx, PHP-FPM et Redis, et le cache serveur face à la personnalisation par IA.
Un serveur PrestaShop surchargé se reconnaît vite : pages lentes, erreurs 502 ou 504, panier qui ne répond plus. La machine est rarement seule en cause. Un module qui appelle une API pendant l’affichage, une requête SQL sans index, un robot qui parcourt les filtres ou un pool PHP-FPM mal dimensionné produisent les mêmes symptômes. Ajouter des ressources avant de trouver la cause déplace le problème.
Cet article suit l’ordre d’une intervention : mesurer, lire les journaux, isoler, corriger, puis monter en charge. Les leviers communs à WordPress et PrestaShop (OPcache, buffer pool InnoDB, hébergement) sont dans notre guide sur la performance serveur d’un CMS. La supervision continue fait l’objet de notre guide de monitoring serveur.
Mesurer pendant le ralentissement
Relevez l’état du serveur au moment du problème. En SSH :
nproc
uptime
ps -eo pid,pcpu,pmem,etime,args --sort=-pcpu | head -n 15
vmstat 1 5
free -h
df -h
Une charge moyenne (uptime) durablement supérieure au nombre de cœurs (nproc) signifie que des processus attendent. Dans vmstat, une colonne wa élevée indique une attente disque, et des valeurs dans si et so un recours au swap. Un disque plein bloque le cache et les sessions : df -h l’écarte en une seconde.
| Symptôme | Cause probable | Vérification |
|---|---|---|
| 502 ou 504 en série | Pool PHP-FPM saturé | max children reached sur la page de statut |
mysqld en tête du CPU | Requête SQL coûteuse | Journal des requêtes lentes, EXPLAIN |
| Toutes les pages lentes après une installation | Module dans un hook global | Profileur PrestaShop |
Rafales d’URL avec ?q= | Robots sur les facettes | Journal d’accès Nginx |
| Erreur 500 ou page blanche | Exception, mémoire épuisée | var/logs/prod-AAAA-MM-JJ.log |
| Processus inconnu gourmand | Compromission possible | Section « Prévenir les crashs » |
Lire PHP-FPM : statut et slow log
Activez la page de statut et le slow log dans le pool, souvent /etc/php/8.4/fpm/pool.d/www.conf selon la distribution :
pm.status_path = /fpm-status
slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 3s
D’après la documentation PHP, listen queue compte les requêtes en attente d’un processus libre : une valeur qui reste positive signale un pool saturé. max children reached indique si la limite a déjà été atteinte, et slow requests le nombre de requêtes trop longues. Réservez cette page à l’adresse locale.
Le slow log enregistre la pile d’appels de chaque requête lente. Les chemins désignent souvent le module :
grep -o "modules/[a-z0-9_]*" /var/log/php-fpm/www-slow.log | sort | uniq -c | sort -rn | head
Lire MySQL ou MariaDB
Le journal des requêtes lentes est désactivé par défaut et long_query_time vaut 10 secondes, trop haut pour une boutique :
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SHOW VARIABLES LIKE 'slow_query_log_file';
Ce réglage disparaît au redémarrage ; reportez-le dans [mysqld] pour le garder. Regroupez ensuite les requêtes par temps cumulé :
mysqldumpslow -s t -t 10 /var/lib/mysql/nom-du-serveur-slow.log
Si EXPLAIN affiche type = ALL avec un rows élevé, la table est lue en entier. Ajoutez un index sur la colonne filtrée, après sauvegarde et test en préproduction, puis relancez EXPLAIN :
ALTER TABLE `ps_nom_de_table` ADD INDEX `idx_nom_colonne` (`nom_colonne`);
Chaque index ralentit les écritures : n’en ajoutez pas sans preuve.
Isoler le module responsable
PrestaShop 9.2 propose l’option « Outil de debug » (« Debug profiler » dans le back-office en anglais), section Mode debug de Paramètres avancés > Performances, liée à la constante _PS_DEBUG_PROFILING_. Elle affiche sous chaque page le temps et la mémoire par hook et par module, ainsi que les requêtes SQL. Utilisez-la en préproduction : elle expose des détails internes. Le mode debug (_PS_MODE_DEV_) affiche les erreurs, pas les temps.
Désactivez ensuite le module suspect en période creuse et mesurez à nouveau. Si le back-office est inaccessible, renommer son dossier dans modules/ l’isole. Ne changez qu’une chose à la fois. Pour auditer un module d’IA, voyez notre checklist des plugins IA.
Les modules d’IA : l’attente réseau
Un module qui appelle une API d’IA pendant l’affichage ne calcule rien sur votre serveur : il attend. Le processus PHP-FPM reste bloqué jusqu’à la réponse. Avec quelques visiteurs simultanés, tout le pool est occupé.
grep -rn "curl_exec\|GuzzleHttp\|HttpClient" modules/nom_du_module/
Un appel déclenché par un hook display* ou un contrôleur front-office s’exécute à chaque affichage. Déplacez-le vers le back-office ou une file d’attente traitée par une tâche planifiée, et fixez toujours un délai (CURLOPT_TIMEOUT, option timeout de Guzzle) :
0 2 * * * /usr/bin/php /chemin/prestashop/modules/nom_du_module/cron/traiter_file.php >/dev/null 2>&1
Stockez chaque réponse sous une empreinte SHA-256 du contenu envoyé : si la fiche n’a pas changé, aucun appel ne part. Voir aussi notre guide des tâches cron.
Contenir les robots sur les facettes
Les filtres du module ps_facetedsearch produisent des URL avec le paramètre q, aux combinaisons presque infinies. Le robots.txt généré par PrestaShop 9.2 contient Disallow: /*?q=, mais seuls les robots respectueux le suivent.
Une requête qui se dit Googlebot se vérifie par DNS inverse (nom en googlebot.com, google.com ou googleusercontent.com), puis DNS direct vers la même adresse. Limitez ensuite le débit sur ces seules URL : Nginx ne compte pas une requête dont la clé est vide.
# Bloc http
map $arg_q $ps_cle_facettes {
"" "";
default $binary_remote_addr;
}
limit_req_zone $ps_cle_facettes zone=ps_facettes:10m rate=30r/m;
# Bloc server de la boutique
limit_req zone=ps_facettes burst=10 nodelay;
limit_req_status 429;
Nginx répond 503 par défaut ; 429 est plus explicite. Google réduit son exploration face aux codes 500, 503 ou 429, mais une URL qui les renvoie plusieurs jours peut sortir de l’index. Voir notre guide de protection d’un serveur web et notre analyse de logs SEO.
Activer les caches
Dans Paramètres avancés > Performances, gardez le cache Smarty actif et activez la concaténation, la compression et la mise en cache des CSS et JavaScript.
Le cache de données natif de PrestaShop 9.2 propose Memcached (extensions Memcache ou Memcached), APC et Xcache. Redis et Valkey passent par un module tiers : voir notre guide Valkey ou Redis pour PrestaShop. Valkey a publié le 26 octobre 2026 des versions de sécurité pour ses branches 7.2 à 9.1 : appliquez-les.
Régler PHP-FPM sans swapper
pm.max_children fixe le nombre de requêtes PHP simultanées. Mesurez la mémoire moyenne d’un processus en trafic réel :
ps -eo rss,args | grep '[p]hp-fpm' | awk '{s+=$1; n++} END {printf "%.0f Mo en moyenne\n", s/n/1024}'
Divisez la mémoire réservée à PHP par cette valeur, un peu surestimée car la mémoire partagée est comptée plusieurs fois. Les 512 Mo de memory_limit recommandés par PrestaShop sont un plafond par requête, pas une moyenne.
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
pm.max_requests = 500
request_terminate_timeout = 55s
pm.max_requests recycle les processus contre les fuites de mémoire. request_terminate_timeout reste inférieur au fastcgi_read_timeout de Nginx, 60 secondes par défaut. Testez avant de recharger :
sudo php-fpm8.4 -t && sudo systemctl reload php8.4-fpm
PrestaShop 9.1 accepte PHP 8.1 à 8.5, avec 8.5 recommandé. Après les failles corrigées le 21 octobre 2026, une version à jour s’impose : voir notre article sur PHP2Shell et notre guide PHP et MySQL pour PrestaShop.
Monter en charge avec Nginx, PHP-FPM et Redis
Quand un nœud bien réglé ne suffit plus, ajoutez un nœud identique (PHP, extensions, code) :
upstream prestashop_php {
least_conn;
server 10.0.0.11:9000 max_fails=3 fail_timeout=30s;
server 10.0.0.12:9000 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name boutique.example;
root /var/www/prestashop;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass prestashop_php;
fastcgi_read_timeout 60s;
}
}
least_conn choisit le nœud le moins occupé. Par défaut, max_fails vaut 1 et fail_timeout 10 secondes. Nginx open source écarte un nœud après des échecs réels, sans le sonder : les vérifications actives relèvent de NGINX Plus. Chaque pool n’accepte que Nginx :
listen = 10.0.0.11:9000
listen.allowed_clients = 10.0.0.1
Ce que les nœuds doivent partager
Le panier et l’identité du client sont dans un cookie chiffré nommé PrestaShop- suivi d’une empreinte. Tous les nœuds doivent partager les clés cookie_key et cookie_iv de app/config/parameters.php. Les sessions PHP servent aux notifications du front-office, au back-office et à certains modules : stockez-les dans Redis ou Valkey via phpredis.
session.save_handler = redis
session.save_path = "tcp://10.0.0.20:6379?auth[]=sessions&auth[]=MOT_DE_PASSE&timeout=2&read_timeout=2"
Selon phpredis, timeout vaut 86 400 secondes par défaut et read_timeout 0 : sans réglage, PHP peut rester bloqué. Séparez l’instance des sessions de celle du cache, avec noeviction pour qu’une instance pleine refuse les écritures plutôt que d’effacer des sessions :
bind 10.0.0.20
protected-mode yes
maxmemory 512mb
maxmemory-policy noeviction
Sur 64 bits, maxmemory vaut 0, soit aucune limite : fixez-la. var/cache reste local à chaque nœud ; videz-le partout après un déploiement. Les images téléversées doivent être accessibles à tous les nœuds.
Le cache de pages, en dernier
Le cache FastCGI de Nginx sert une page sans exécuter PHP, uniquement pour les visiteurs sans panier ni connexion :
fastcgi_cache_path /var/cache/nginx/prestashop levels=1:2 keys_zone=ps_cache:50m max_size=1g inactive=30m;
map $http_cookie $ps_sans_cache {
default 0;
"~PrestaShop-" 1;
}
# Dans le bloc location PHP
fastcgi_cache ps_cache;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_valid 200 5m;
fastcgi_cache_bypass $ps_sans_cache;
fastcgi_no_cache $ps_sans_cache;
add_header X-Cache $upstream_cache_status;
Nginx ne stocke pas une réponse qui contient Set-Cookie : ne forcez pas ce comportement. Excluez l’administration, le panier, le compte et la commande. Un prix modifié reste affiché jusqu’à l’expiration du cache. Pour des recommandations par IA, servez la page commune en cache et chargez le bloc personnalisé à part, en Cache-Control: private ; un cookie de segment modifiable ne doit jamais fixer un prix. Voir notre article sur la personnalisation par IA.
Prévenir les crashs
- Boucle de redirection : domaine enregistré différent de l’URL appelée, redirection HTTPS déclarée deux fois, ou en-tête
X-Forwarded-Protoignoré derrière un proxy.curl -I -L --max-redirs 10 https://votre-domaine.fr/confirme la boucle. - Mémoire épuisée : un export ou un module qui charge tout le catalogue. Le journal
var/logs/désigne le script. - Directive refusée :
php_valuedans.htaccessprovoque souvent une erreur 500 hors mod_php. Voir notre guide de l’erreur 500 PrestaShop. - Compromission : processus inconnu, fichiers PHP récents (
find /chemin/boutique -name "*.php" -mtime -30). Suivez notre procédure boutique piratée.
Testez chaque mise à jour sur une copie, versionnez la configuration serveur, gardez _PS_MODE_DEV_ à false en production et testez vos restaurations. Avant un temps fort, un test de charge (k6, Apache JMeter) doit suivre un parcours réel jusqu’à la commande, après accord de l’hébergeur.
Questions fréquentes
Faut-il ajouter un second serveur dès que la boutique ralentit ?
Non. Consultez d’abord le statut PHP-FPM, les requêtes lentes et le profileur. Une requête sans index, un module qui attend une API ou un robot sur les facettes ne se corrigent pas avec une machine de plus.
Un hébergement mutualisé peut-il supporter un module d’IA ?
Rarement s’il appelle une API à chaque affichage. Les processus PHP y sont limités et le pool est inaccessible. Un traitement asynchrone, ou un VPS, est plus raisonnable.
Que se passe-t-il si Redis tombe ?
Les sessions non persistées sont perdues : déconnexion du back-office, notifications et données de modules. Le panier, enregistré en base et référencé par le cookie, est conservé. Activez AOF ou RDB si cette perte vous gêne.
Limiter les robots peut-il nuire au référencement ?
Oui, si la règle touche des pages utiles ou dure plusieurs jours. Ciblez les URL de facettes, déjà exclues par le robots.txt de PrestaShop, et vérifiez l’identité de Googlebot.
Sources
- PrestaShop, System requirements (PrestaShop 9) : https://devdocs.prestashop-project.org/9/basics/installation/system-requirements/
- Code de PrestaShop 9.2.0, lu localement :
classes/cache/,classes/Cookie.php,classes/Tools.php(generateRobotsFile),config/defines.inc.php,DebugModeType.php. - PHP, FPM configuration : https://www.php.net/manual/en/install.fpm.configuration.php
- PHP, FPM status page : https://www.php.net/manual/en/fpm.status.php
- MySQL 8.4, The Slow Query Log : https://dev.mysql.com/doc/refman/8.4/en/slow-query-log.html
- nginx, upstream, fastcgi et limit_req : https://nginx.org/en/docs/http/ngx_http_upstream_module.html, https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html, https://nginx.org/en/docs/http/ngx_http_limit_req_module.html
- phpredis, PHP Session handler : https://github.com/phpredis/phpredis
- Redis, Key eviction : https://redis.io/docs/latest/develop/reference/eviction/
- Valkey, Releases : https://github.com/valkey-io/valkey/releases
- Google, Reduce the Google crawl rate : https://developers.google.com/crawling/docs/crawlers-fetchers/reduce-crawl-rate
- Google, Verifying Googlebot : https://developers.google.com/crawling/docs/crawlers-fetchers/verify-google-requests