WordPress « Mémoire épuisée » : augmenter les limites correctement (là où ça compte)

Cet article vous a aidé ?

Cette erreur fatale « Allowed memory size exhausted » n’est pas seulement agaçante. C’est le genre de panne qui survient à 2 h du matin, juste après une mise à jour de plugin et juste avant le lancement d’une campagne. Le site fonctionne… jusqu’à ce qu’il ne fonctionne plus. Puis il entraîne l’administration, le paiement ou le cron avec lui.

La solution n’est rarement « il suffit d’augmenter wp-config ». La mémoire WordPress est une pile de limites réparties entre PHP, PHP-FPM, conteneurs, cgroups et parfois le plafond invisible du fournisseur d’hébergement. Augmenter la mauvaise limite et rien ne change. Augmenter la bonne sans comprendre pourquoi vous en avez besoin et vous masquerez une fuite jusqu’à provoquer une panne.

Ce que l’erreur signifie vraiment (et ce qu’elle ne signifie pas)

Le crash canonique de WordPress ressemble à ceci :

  • « Fatal error: Allowed memory size of X bytes exhausted (tried to allocate Y bytes) »

Ce message vient de PHP, pas de WordPress. WordPress n’est que le messager qui a reçu le coup. PHP a atteint un plafond strict et a interrompu la requête. Le plafond est généralement memory_limit, mais la cause sous-jacente peut être très différente :

  • Un plugin/thème charge trop de données en mémoire (courant : rapports WooCommerce, constructeurs de pages, importateurs).
  • Une boucle ou une récursion bugée créant des tableaux/objets en croissance continue.
  • Un chemin de traitement d’image utilisant Imagick/GD et conservant plusieurs bitmaps pleine taille.
  • Fragmentation d’OPcache ou OPcache trop petit dans un écosystème de plugins volumineux (peut se manifester par des lenteurs aléatoires ou des 502 plutôt que « memory exhausted », mais c’est la même famille d’échec).
  • Un conteneur ou une VM tué par le OOM killer du noyau (pas de fatal PHP amical ; juste un worker mort).
  • Un plafond de plan d’hébergement : vous augmentez la mémoire PHP, mais le fournisseur bride ou tue le processus quand même.

Voici l’essentiel : augmenter la mémoire n’est pas une condition de victoire. C’est un outil. Vous augmentez la mémoire pour (a) remettre le service en ligne en toute sécurité, puis (b) rendre le profil mémoire de la requête raisonnable afin de pouvoir la réduire à nouveau. Si vous ne faites que l’étape (a), vous avez simplement différé la panne et rendu le comportement plus étrange.

Une citation pour rester lucide : « L’espoir n’est pas une stratégie. » (Maxime des opérations, souvent attribuée à divers responsables techniques ; idée paraphrasée.)

Faits et contexte intéressants (parce que ce problème a une histoire)

  1. Le memory_limit par défaut de PHP était autrefois faible. Les anciennes versions de PHP étaient souvent livrées avec 128M, suffisant pour des blogs mais ridiculement insuffisant pour des piles WordPress modernes.
  2. WordPress a deux concepts de “mémoire”. Les constantes WP_MEMORY_LIMIT et WP_MAX_MEMORY_LIMIT peuvent demander des limites plus élevées, mais elles ne peuvent pas dépasser ce que PHP autorise.
  3. WooCommerce a changé les attentes. L’e-commerce a transformé « un site » en « une application », et les charges admin/rapports sont devenues suffisamment gourmandes en mémoire.
  4. PHP-FPM a rendu normales les limites par pool. Avant la domination de PHP-FPM, ajuster par site était plus compliqué ; maintenant vous pouvez isoler les sites via des configs de pool (quand vous contrôlez l’hôte).
  5. OPcache est devenu une fonctionnalité par défaut de performance. Il a aussi introduit un nouveau mode d’échec : l’épuisement ou la fragmentation du cache de code qui peut ressembler à des pannes aléatoires.
  6. Les conteneurs ont changé la donne. Un conteneur peut avoir un memory_limit PHP élevé mais être OOM-killé parce que la limite cgroup est plus basse.
  7. L’hébergement mutualisé ajoute des plafonds invisibles. Les fournisseurs imposent souvent des caps par compte (RSS, CPU seconds, entry processes) ; augmenter memory_limit peut être purement symbolique.
  8. Le cron WordPress n’est pas un « vrai cron ». WP-Cron est déclenché par le trafic web ; lorsqu’il exécute des tâches lourdes dans une requête, des pics mémoire surviennent à des moments inopportuns.

Une petite blague, parce qu’on l’a bien méritée : les erreurs de mémoire WordPress sont comme le café du bureau — quand vous remarquez enfin le problème, il est déjà trop tard et tout le monde est fâché.

Mode d’intervention rapide (vérifier d’abord/ensuite/enfin)

Voici la checklist « arrêtez de deviner ». Vous pouvez la faire en moins de 15 minutes sur la plupart des systèmes.

Premier point : est-ce le memory_limit PHP, ou le noyau/conteneur qui vous tue ?

  • Si vous voyez le fatal PHP explicite « Allowed memory size exhausted », c’est presque toujours memory_limit (ou une constante WordPress qui n’a pas réussi à l’augmenter).
  • Si vous voyez des 502/504 sans fatal PHP, vérifiez les logs PHP-FPM et les événements OOM du noyau/cgroup. C’est une autre piste.

Second point : quel SAPI et quelle config sont réellement utilisés (FPM vs CLI) ?

  • php -i est le CLI. Vos requêtes web peuvent utiliser un php.ini différent sous PHP-FPM.
  • Utilisez un endpoint ou les logs pour confirmer les paramètres runtime du SAPI web.

Troisième point : identifiez le chemin de requête et le coupable

  • Est-ce seulement wp-admin ? seulement la page de paiement ? seulement WP-Cron ? seulement un endpoint précis ?
  • Activez la journalisation ciblée, reproduisez une fois et récupérez la trace de pile ou la liste de plugins corrélée au pic.

Quatrième point : choisissez le bon niveau de remédiation

  • Urgence : augmentez la limite effective au niveau qui la contrôle pour restaurer le service.
  • Stabiliser : isolez avec le tuning du pool PHP-FPM, réduisez la concurrence si besoin.
  • Corriger la cause racine : bug de plugin/thème, taille de requête, taille de lot d’import, stratégie de cache, planning WP-Cron.

Où vivent les limites mémoire : la pile qui décide de votre sort

Considérez la mémoire WordPress comme un ensemble de portes. La plus petite porte l’emporte. Vous pouvez peindre « 512M » sur la porte WordPress toute la journée ; si la porte PHP est à 128M, vous ne passerez pas.

Porte 1 : constantes WordPress (des demandes, pas des garanties)

  • WP_MEMORY_LIMIT : prévu pour le front-end.
  • WP_MAX_MEMORY_LIMIT : prévu pour les tâches d’administration (mises à jour, importations, etc.).

Ces constantes peuvent augmenter la limite jusqu’à la limite de PHP, selon que PHP autorise la modification de memory_limit à l’exécution.

Porte 2 : paramètre runtime PHP (le plafond strict)

memory_limit est un paramètre PHP, défini via php.ini, la config du pool FPM, la config Apache ou des overrides par répertoire (selon le SAPI et les permissions). C’est généralement ce paramètre qui produit le message « Allowed memory size exhausted ».

Porte 3 : configuration du pool PHP-FPM (isolation par site)

Si vous gérez votre propre hôte (VM/matériel nu), les pools PHP-FPM permettent de définir des limites et comportements par site. Vous pouvez imposer memory_limit via php_admin_value[memory_limit] (non modifiable par les scripts), ou autoriser php_value (modifiable).

Porte 4 : contraintes du gestionnaire de processus (concurrence)

L’épuisement mémoire n’est pas seulement « une requête est grosse ». C’est souvent « beaucoup de requêtes sont moyennement grosses ». Les réglages FPM comme pm.max_children déterminent combien de workers peuvent tourner en parallèle. Si chaque worker peut utiliser jusqu’à 512M et que vous autorisez 20 workers, vous promettez au système 10 Go de mémoire. Le noyau ne sera pas impressionné.

Porte 5 : le système d’exploitation, les cgroups et l’OOM killer

Sur les conteneurs et de nombreuses plateformes managées, la limite réelle est la limite cgroup. Le noyau peut tuer des workers PHP-FPM (ou tout le conteneur) sans fatal PHP. Dans Kubernetes vous verrez OOMKilled. Avec systemd vous pouvez voir la comptabilisation et l’application des limites mémoire.

Porte 6 : politique du fournisseur d’hébergement

Les hébergeurs mutualisés et certaines plateformes WordPress gérées appliquent des caps par compte (RSS, CPU seconds, entry processes). Vous pourriez définir memory_limit à 512M et être quand même tué ou bridé parce que la limite du fournisseur est plus basse ou parce que votre offre l’interdit.

Tâches pratiques (commandes, sorties et décisions)

Ce sont des contrôles de niveau production. Chacun inclut : la commande, un exemple de sortie, ce que cela signifie et la décision à prendre.

Task 1: Confirm the PHP version and SAPI used by CLI (baseline)

cr0x@server:~$ php -v
PHP 8.2.12 (cli) (built: Oct 12 2024 10:11:21) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.12, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.12, Copyright (c), by Zend Technologies

Signification : Il s’agit de PHP en CLI. Utile pour les tâches WP-CLI, pas définitif pour les requêtes web.

Décision : Si l’erreur survient via le trafic web, ne supposez pas que cette configuration s’applique. Passez aux vérifications FPM/web.

Task 2: Find which php.ini CLI is using (avoid config mirages)

cr0x@server:~$ php --ini
Configuration File (php.ini) Path: /etc/php/8.2/cli
Loaded Configuration File:         /etc/php/8.2/cli/php.ini
Scan for additional .ini files in: /etc/php/8.2/cli/conf.d
Additional .ini files parsed:      /etc/php/8.2/cli/conf.d/10-opcache.ini

Signification : Vous savez maintenant d’où le CLI lit sa config.

Décision : Si WP-CLI échoue avec un memory exhausted, vous pouvez ajuster ceci. Si le web échoue, vous devez vérifier la config FPM ensuite.

Task 3: Read the effective memory_limit for CLI

cr0x@server:~$ php -r 'echo ini_get("memory_limit").PHP_EOL;'
128M

Signification : Le CLI est plafonné à 128M.

Décision : Si des imports WP-CLI ou des jobs cron échouent, augmentez le memory_limit du CLI (ou lancez avec -d memory_limit=... pour des tâches ponctuelles).

Task 4: Confirm PHP-FPM service is present and running (web lane)

cr0x@server:~$ systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled; preset: enabled)
     Active: active (running) since Fri 2025-12-27 08:41:10 UTC; 2h 11min ago
       Docs: man:php-fpm8.2(8)
   Main PID: 1042 (php-fpm8.2)
      Tasks: 23 (limit: 18963)
     Memory: 612.4M

Signification : FPM fonctionne ; vous pouvez inspecter les configs de pool et les logs.

Décision : Si vous voyez une grosse valeur « Memory: » ici et que vous êtes proche des limites de la machine, revoyez pm.max_children et la mémoire par worker.

Task 5: Locate the active FPM pool configs

cr0x@server:~$ grep -R "^\[" -n /etc/php/8.2/fpm/pool.d/*.conf
/etc/php/8.2/fpm/pool.d/www.conf:1:[www]
/etc/php/8.2/fpm/pool.d/site.conf:1:[site]

Signification : Vous avez plusieurs pools. Utile pour l’isolation ; source possible de confusion.

Décision : Identifiez quel pool sert le vhost WordPress, puis ajustez ce pool, pas un autre par erreur.

Task 6: Check the web SAPI memory_limit via FPM pool settings

cr0x@server:~$ grep -R "memory_limit" -n /etc/php/8.2/fpm/pool.d/*.conf
/etc/php/8.2/fpm/pool.d/site.conf:38:php_admin_value[memory_limit] = 256M

Signification : Ce pool force 256M, et les scripts ne peuvent pas le dépasser car c’est une valeur administrateur.

Décision : Si WordPress demande 512M mais meurt à 256M, cette ligne en est la cause. Changez-la ici et rechargez FPM.

Task 7: Validate whether the error is in PHP logs (not just the browser)

cr0x@server:~$ sudo tail -n 50 /var/log/php8.2-fpm.log
[27-Dec-2025 10:38:55] WARNING: [pool site] child 2517 said into stderr: "PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 1048576 bytes) in /var/www/html/wp-includes/class-wpdb.php on line 2345"

Signification : C’est l’enregistrement faisant foi : plafond de 256M (268 435 456 octets) atteint durant un traitement de base de données.

Décision : Augmentez le memory_limit web (ou corrigez la requête/plugin). Envisagez aussi pourquoi wpdb charge autant (rapports, recherche, options autoload volumineuses).

Task 8: Check for kernel OOM kills (the “no PHP fatal” scenario)

cr0x@server:~$ sudo dmesg -T | tail -n 20
[Sat Dec 27 10:41:02 2025] Out of memory: Killed process 2517 (php-fpm8.2) total-vm:1462256kB, anon-rss:912324kB, file-rss:0kB, shmem-rss:0kB, UID:33 pgtables:3112kB oom_score_adj:0
[Sat Dec 27 10:41:02 2025] oom_reaper: reaped process 2517 (php-fpm8.2), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

Signification : Le noyau a tué un worker PHP-FPM. Ce n’est pas un événement memory_limit PHP ; c’est une pression mémoire du nœud/conteneur.

Décision : Réduisez la concurrence (pm.max_children), augmentez la mémoire hôte, baissez le memory_limit par worker, ou corrigez l’usage mémoire de la requête. Si vous êtes en conteneurs, augmentez aussi les limites cgroup.

Task 9: Inspect the container cgroup memory limit (Docker / systemd / cgroups v2)

cr0x@server:~$ cat /sys/fs/cgroup/memory.max
536870912

Signification : Le groupe de processus est limité à 512MB au total. Si vous définissez PHP memory_limit à 512M et autorisez plusieurs workers, vous obtiendrez des OOM kills.

Décision : Soit augmentez la limite cgroup, soit réduisez le memory_limit PHP (par ex. 256M) et ajustez la concurrence FPM pour tenir dans le budget.

Task 10: Measure real memory use per PHP-FPM child (stop guessing)

cr0x@server:~$ ps -o pid,rss,cmd -C php-fpm8.2 --sort=-rss | head -n 8
  PID   RSS CMD
 2519 412980 php-fpm: pool site
 2518 356112 php-fpm: pool site
 2516 198344 php-fpm: pool site
 1042  65244 php-fpm: master process (/etc/php/8.2/fpm/php-fpm.conf)

Signification : Le RSS est la mémoire résidente réelle. Vous avez des workers dans la fourchette 200–400 MB.

Décision : Utilisez le RSS au haut percentile (pas le meilleur cas) pour dimensionner pm.max_children. Si deux workers atteignent déjà 400MB chacun, ne lancez pas 10 sur une machine à 2GB.

Task 11: Check WordPress’ view of memory (it’s informative, not authoritative)

cr0x@server:~$ wp --path=/var/www/html option get home
https://example.internal

Signification : WP-CLI peut parler à la base de code du site. Vous pouvez maintenant lancer des diagnostics.

Décision : Si WP-CLI lui-même échoue avec des erreurs mémoire, lancez-le temporairement avec une limite plus élevée pour diagnostiquer.

cr0x@server:~$ wp --path=/var/www/html --info
OS:     Linux 6.5.0-1022-aws #24~22.04.1-Ubuntu SMP
Shell:  /bin/bash
PHP binary:     /usr/bin/php8.2
PHP version:    8.2.12
php.ini used:   /etc/php/8.2/cli/php.ini
WP-CLI root dir:        /home/cr0x/.wp-cli
WP-CLI version: 2.10.0

Signification : Confirme encore que c’est le CLI. Utile, mais ne le confondez pas avec le comportement web.

Décision : Si la panne de production est uniquement web, concentrez-vous sur les paramètres FPM et les logs web.

Task 12: Identify heavy plugins quickly (and disable safely if needed)

cr0x@server:~$ wp --path=/var/www/html plugin list --status=active
+--------------------------+--------+-----------+---------+
| name                     | status | update    | version |
+--------------------------+--------+-----------+---------+
| woocommerce              | active | available | 8.6.1   |
| elementor                | active | none      | 3.20.2  |
| wordfence                | active | none      | 7.11.2  |
| wp-mail-smtp             | active | none      | 4.4.0   |
+--------------------------+--------+-----------+---------+

Signification : Vous avez les suspects habituels : e‑commerce, constructeur de pages, plugin de sécurité. Chacun peut augmenter la mémoire sur certains endpoints.

Décision : Si vous avez besoin d’une récupération d’urgence, désactivez le plugin suspect (un à la fois) après avoir pris un snapshot/sauvegarde et informé des impacts.

Task 13: Check autoloaded options size (silent memory hog)

cr0x@server:~$ wp --path=/var/www/html db query "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
+------------+
| autoload_mb|
+------------+
| 12.47      |
+------------+

Signification : 12.47MB d’options autoloadées est élevé. Les options autoloadées sont chargées sur de nombreuses requêtes, augmentant la mémoire de base.

Décision : Auditez les options volumineuses, réduisez l’autoload quand c’est sûr et envisagez un cache d’objet.

Task 14: Find top autoloaded options (targets for cleanup)

cr0x@server:~$ wp --path=/var/www/html db query "SELECT option_name, ROUND(LENGTH(option_value)/1024/1024,2) AS mb FROM wp_options WHERE autoload='yes' ORDER BY LENGTH(option_value) DESC LIMIT 10;"
+------------------------------+------+
| option_name                  | mb   |
+------------------------------+------+
| _transient_timeout_wc_report | 3.21 |
| elementor_css                | 2.44 |
| wordfence_waf_options        | 1.18 |
| rewrite_rules                | 0.94 |
+------------------------------+------+

Signification : Des transients et blobs générés par le constructeur vivent en autoload. Cela gonfle la mémoire à chaque initialisation de WordPress.

Décision : Corrigez la source (paramètres du plugin), purgez/reconstruisez si approprié et assurez-vous que les transients ne sont pas autoloadés indéfiniment.

Task 15: Check OPcache status (when “memory” is really code cache pressure)

cr0x@server:~$ php -r 'print_r(opcache_get_status(false)["memory_usage"]);'
Array
(
    [used_memory] => 118901488
    [free_memory] => 1562032
    [wasted_memory] => 4381656
    [current_wasted_percentage] => 3.55
)

Signification : OPcache a ~1.5MB libre. C’est serré. Avec des déploiements fréquents ou beaucoup de plugins, vous pouvez atteindre le mur.

Décision : Augmentez opcache.memory_consumption et envisagez opcache.max_accelerated_files. Revoyez également la stratégie de reload pour réduire la fragmentation.

Task 16: Confirm current FPM process manager settings (concurrency math)

cr0x@server:~$ grep -nE "^(pm\.|php_admin_value\[memory_limit\])" /etc/php/8.2/fpm/pool.d/site.conf
23:pm = dynamic
24:pm.max_children = 20
25:pm.start_servers = 4
26:pm.min_spare_servers = 4
27:pm.max_spare_servers = 8
38:php_admin_value[memory_limit] = 256M

Signification : Vous pouvez exécuter 20 workers, chacun autorisé à 256M. C’est une allocation théorique de 5GB au pire, plus overhead.

Décision : Sur un hôte 2–4GB, c’est une panne en devenir. Baissez pm.max_children ou réduisez la mémoire par worker, puis testez la charge.

Task 17: Reload FPM safely after changes (don’t bounce production unless required)

cr0x@server:~$ sudo systemctl reload php8.2-fpm

Signification : FPM recharge la config de façon gracieuse ; les requêtes existantes se terminent, les nouvelles utilisent les paramètres mis à jour.

Décision : Préférez reload plutôt que restart pendant les heures d’activité, sauf besoin d’un reset dur (ex. workers bloqués).

Task 18: Verify effective memory_limit via a web request (ground truth)

cr0x@server:~$ curl -sS -H "Host: example.internal" http://127.0.0.1/wp-admin/admin-ajax.php?action=heartbeat | head
0

Signification : Le web répond. Cela ne montre pas directement le memory_limit, mais c’est un contrôle de sanité rapide après des changements.

Décision : Si l’erreur se produisait sur des endpoints admin, reproduisez maintenant l’action exacte qui échouait et surveillez les logs pour des fatals liés à la mémoire.

Augmenter les limites correctement : recettes selon le modèle d’hébergement

Voici la règle : définissez les limites le plus près possible de la couche qui les fait respecter. Les constantes WordPress sont utiles pour demander un ajustement. Elles ne sont pas la gouvernance.

Scenario A: You control the VM/bare metal (Nginx/Apache + PHP-FPM)

1) Set per-pool memory_limit (preferred)

Éditez votre fichier de pool (exemple : /etc/php/8.2/fpm/pool.d/site.conf) :

  • Utilisez php_admin_value[memory_limit] = 256M (ou 384M/512M) quand vous voulez l’imposer.
  • Utilisez php_value[memory_limit] = 256M si vous voulez permettre aux applications d’outrepasser (généralement vous ne le faites pas).

Puis rechargez FPM et confirmez que les logs n’affichent plus d’exhaustion.

2) Tune concurrency with pm.max_children

Augmenter le memory_limit sans tuner la concurrence est la façon de transformer une panne d’une seule requête en OOM complet du nœud. Faites le calcul :

  • Mesurez le RSS réel des workers (Task 10).
  • Choisissez un budget sûr : laissez de la place pour le cache OS, la base de données et le serveur web.
  • Réglez pm.max_children pour que RSS_max × children tienne dans le budget.

3) Keep WordPress constants modest (and honest)

Dans wp-config.php vous pouvez définir :

  • define('WP_MEMORY_LIMIT', '256M');
  • define('WP_MAX_MEMORY_LIMIT', '512M');

Cela aide WordPress à demander plus de mémoire pour les tâches d’administration sans donner à chaque requête front-end un chèque en blanc. Si votre pool PHP-FPM impose 256M, définir WP_MAX_MEMORY_LIMIT à 512M n’aidera pas. Ce décalage est votre signal : décidez si l’administration a réellement besoin de 512M, ou si le plugin/rapport doit être corrigé.

Scenario B: Shared hosting (cPanel-style) with limited control

C’est là où les conseils sur internet périssent. Vous ne contrôlez peut-être pas les pools PHP-FPM. Votre fournisseur peut exécuter suPHP, LSAPI ou son propre wrapper.

Ordre des opérations :

  1. Vérifiez ce que vous pouvez changer (MultiPHP INI Editor, paramètres PHP par domaine, etc.).
  2. Tentez d’augmenter memory_limit via l’UI du fournisseur (idéal).
  3. Si possible, ajoutez ou éditez .user.ini avec memory_limit = 256M. Attention : les changements peuvent prendre quelques minutes.
  4. Si vous utilisez Apache mod_php et que c’est autorisé, utilisez des directives .htaccess (souvent désactivées chez les hôtes modernes).
  5. Si aucune de ces options ne fonctionne, acceptez la réalité : vous avez atteint les limites du plan. Optimisez ou migrez/montez en gamme.

Deux avertissements :

  • Ne mettez pas aveuglément 1024M parce que vous avez trouvé un post de 2016. Cela ne résoudra pas un plafond fournisseur et masquera une fuite de plugin jusqu’à ce que votre compte soit throttlé.
  • Ne supposez pas que les logs d’erreur sont complets. L’hébergement mutualisé peut supprimer des signaux clés. Utilisez la journalisation côté application quand c’est possible.

Scenario C: Docker / Compose

Dans les conteneurs, vous avez au moins deux limites : le memory_limit PHP et la limite mémoire du conteneur. Il faut les aligner.

Ce qui est bien :

  • La limite mémoire du conteneur dimensionnée pour gérer la concurrence de pointe.
  • Le nombre de workers PHP-FPM limité pour éviter les OOM kills cgroup.
  • Le memory_limit PHP fixé en-dessous du seuil « trop gros pour échouer » par worker.

Si votre conteneur est limité à 512MB, définir PHP memory_limit à 512M revient à acheter une valise exactement de la taille de la limite aérienne, puis y mettre une brique. Ça tient jusqu’à ce que ça ne tienne plus.

Scenario D: Kubernetes (WordPress behind Ingress)

Dans Kubernetes, traitez la mémoire comme un contrat de ressource :

  • Requests/limits déterminent l’ordonnancement et l’application. Si la limit est basse, le pod sera OOMKilled sous charge.
  • Réglez la concurrence PHP-FPM pour correspondre à ce que votre pod peut supporter.
  • Surveillez les événements OOMKilled, les boucles de redémarrage et les pics de 502 dus à des timeouts en amont.

Si vous ne pouvez pas rendre la mémoire prévisible, vous avez probablement un endpoint de plugin non borné : trop de lignes récupérées, trop de HTML généré, ou une exportation qui tente de construire un fichier entier en RAM.

Quand augmenter la mémoire est une mauvaise solution : plugins, thèmes et vraies fuites

La plupart des incidents « memory exhausted » commencent par un changement : mise à jour d’un plugin, nouveau rapport, import massif, ou une fonction de thème qui s’exécute sur chaque requête.

Comment savoir que vous masquez une fuite

  • L’usage mémoire augmente progressivement dans le temps sur les workers, pas seulement durant un endpoint.
  • La même requête réussit parfois et échoue parfois, selon l’état du cache ou les chemins de code OPcache.
  • Augmenter la mémoire « répare » pendant des jours, puis le problème revient en pire.

Coupables typiques (et le schéma derrière eux)

  • Générateurs de rapports : chargent des tables entières en tableaux PHP. La solution : pagination, limites de requête, exports en streaming ou déplacer le travail en jobs asynchrones.
  • Importateurs : lisent des CSV/XML entiers en mémoire. La solution : traitement par morceaux et lots plus petits.
  • Constructeurs de pages : méta post volumineux et blobs JSON. La solution : réduire les templates, mettre en cache et contrôler les révisions.
  • Plugins de sécurité : scans lourds, règles WAF, écritures fréquentes dans les options. La solution : configurer, planifier hors‑pics et s’assurer que les caches ne sont pas en autoload.
  • Transients non bornés : des données « temporaires » qui deviennent permanentes. La solution : nettoyage et expiration correcte.

Approche pratique : stabiliser, puis isoler

En production, vous ne commencez pas en désinstallant la moitié des plugins. Vous commencez par rendre le système assez stable pour déboguer.

  1. Augmentez la limite effective juste assez pour arrêter le crash.
  2. Réduisez la concurrence si l’hôte est en risque d’OOM.
  3. Reproduisez l’action défaillante en staging avec les mêmes tailles de données.
  4. Désactivez les plugins suspects un par un, en mesurant mémoire et temps de requête.
  5. Corrigez la cause racine ou remplacez le plugin. « Mais on l’a payé » n’est pas une stratégie de performance.

OPcache et les faux-semblants “mémoire épuisée”

Parfois des utilisateurs rapportent « mémoire épuisée » mais ce que vous voyez ce sont des 502, un admin lent et des messages de log concernant OPcache. Symptôme différent, même classe : pression mémoire.

Mode d’échec OPcache à reconnaître

  • Après de nombreux déploiements ou mises à jour de plugins, OPcache se fragmente.
  • Les nouveaux fichiers PHP ne se mettent plus en cache, la performance chute et l’CPU worker monte.
  • Recharger FPM « répare » temporairement car cela réinitialise OPcache.

OPcache n’est pas optionnel sur des sites WordPress très fréquentés. Mais il doit disposer de mémoire et de slots de fichiers suffisants pour mettre en cache votre base de code. Un WordPress moderne avec WooCommerce et quelques dizaines de plugins peut facilement dépasser des valeurs par défaut prudentes.

Trois mini-récits d’entreprise issus du terrain

1) L’incident causé par une mauvaise hypothèse

Ils venaient de migrer un portefeuille de sites WordPress d’un vieil hébergement mutualisé vers une belle VM. L’équipe a fait l’évidence : définir define('WP_MEMORY_LIMIT','512M'); dans wp-config.php sur tous les sites. Ils ont aussi noté en interne : « Problèmes de mémoire résolus. »

Deux semaines plus tard, pendant une fenêtre de mises à jour de plugins, la moitié des sites a commencé à renvoyer des erreurs 502. L’astreignant a cherché dans les timeouts Nginx, les keepalive upstream et le DNS. Ce fut un tour complet de tout sauf du problème.

La cause racine était banale : les pools PHP-FPM étaient configurés avec php_admin_value[memory_limit] = 128M, hérité d’un baseline de hardening. WordPress ne pouvait pas l’outrepasser. Les requêtes d’administration de mise à jour épuisait la mémoire et faisaient planter les workers. Nginx signalait 502 parce que l’amont mourait en cours de requête.

La réparation a pris dix minutes une fois qu’ils ont regardé au bon endroit : augmenter la limite du pool à 256M pour les sites affectés, recharger FPM et relancer les mises à jour. La leçon réelle prit plus de temps : ne jamais considérer les constantes WordPress comme la source de vérité. Elles sont une demande ; la plateforme décide.

2) L’optimisation qui a mal tourné

Un responsable ingénierie voulait un meilleur débit lors d’un lancement produit. L’équipe a augmenté agressivement pm.max_children. Plus de workers signifie plus de requêtes parallèles, non ? Le CPU allait bien en test, et le site semblait plus réactif sur la page d’accueil. Victoire, pendant environ une journée.

Puis l’email marketing est parti. Le trafic checkout a monté en flèche, et la mémoire aussi. Certains endpoints WooCommerce culminaient à quelques centaines de mégaoctets par requête avec des paniers réels et des plugins réels. Avec le nombre de children augmenté, le nœud s’est rapidement retrouvé à court de RAM. Le noyau a commencé à tuer les workers. Les requêtes ont été relancées. La charge a augmenté. Le système s’est enchaîné en une auto‑attaque par déni de service.

Ils ont rollback pm.max_children et augmenté le PHP memory_limit « pour être sûrs ». Cela a aidé un peu, mais seulement parce que ça a réduit la fréquence des fatals PHP tout en maintenant le nœud dans la zone dangereuse.

La configuration stable finale était ennuyeuse : mesurer le RSS peak par worker, définir pm.max_children sur le budget hôte et limiter memory_limit pour qu’une seule requête débridée ne puisse pas emporter tout le nœud. Ils ont aussi déplacé la génération de rapports lourds hors des requêtes admin synchrones vers des jobs en file d’attente.

3) La pratique ennuyeuse mais correcte qui a sauvé la mise

Une autre entreprise exécutait WordPress comme partie d’une plate-forme plus large. Rien de glamour : pools séparés par site, valeurs conservatrices et un processus de changement qui exigeait une chose avant d’ajuster — la mesure.

Ils avaient un petit script qui consignait les points hauts mémoire pour les requêtes lentes et les corrélait avec les chemins d’endpoint. Ce n’était pas un APM sophistiqué. C’était suffisant. Quand une nouvelle version d’un plugin a commencé à consommer plus de mémoire sur wp-admin/admin-ajax.php, l’équipe a repéré la tendance en quelques heures.

Au lieu de monter tous les sites à 512M, ils ont augmenté la mémoire seulement pour le pool affecté, réduit sa concurrence et ouvert un ticket au fournisseur du plugin avec un jeu de données reproductible. Pendant ce temps, le reste de la flotte est resté stable et peu coûteux.

Le jour du lancement, quand le trafic a doublé, ils n’ont pas découvert de nouveau comportement mémoire. Ils avaient déjà la marge. Le site est resté en ligne. Personne n’a écrit de postmortem héroïque, ce qui est le plus beau compliment en opérations.

Erreurs fréquentes : symptôme → cause racine → fix

1) « J’ai mis WP_MEMORY_LIMIT à 512M mais ça meurt toujours à 128M »

Symptôme : Le fatal indique 134,217,728 bytes exhausted (128M) malgré la config WordPress.

Cause racine : Le pool PHP-FPM utilise php_admin_value[memory_limit] ou le php.ini global est plus bas ; les changements runtime sont bloqués.

Fix : Augmentez memory_limit dans la couche qui contrôle (pool FPM/php.ini/UI hébergeur), rechargez FPM et confirmez via les logs.

2) « On a des 502/504, pas de fatal PHP »

Symptôme : Nginx signale des erreurs upstream ; les logs PHP sont silencieux.

Cause racine : Worker tué par l’OOM du noyau, FPM crashé, ou upstream timeout. Pas un événement memory_limit PHP.

Fix : Vérifiez dmesg pour les OOM kills, vérifiez les logs FPM, réduisez pm.max_children, alignez les limites conteneur et corrigez les endpoints mémoire-lourds.

3) « Seul wp-admin échoue, le front-end va bien »

Symptôme : Mises à jour/imports/rapports admin plantent ; les visiteurs peuvent naviguer.

Cause racine : Les tâches admin utilisent des ensembles de données plus grands et peuvent demander WP_MAX_MEMORY_LIMIT, mais la limite du pool PHP est trop basse ou le chemin admin déclenche des plugins lourds.

Fix : Allouez un budget mémoire admin plus élevé si justifié, et optimisez le workflow admin spécifique (batches, pagination, exports).

4) « Ça a commencé après l’activation d’un plugin de sécurité »

Symptôme : Fatals mémoire aléatoires, requêtes lentes, table d’options volumineuse.

Cause racine : Fonctions de scanning/WAF qui augmentent l’overhead par requête ; options/transients mal stockés.

Fix : Ajustez la configuration du plugin, planifiez les scans hors pics, déplacez les caches hors autoload, envisagez un cache d’objet.

5) « Augmenter la mémoire l’a réparé… jusqu’au lendemain »

Symptôme : Incidents récurrents avec une mémoire de base qui monte, ou de nouvelles pages qui déclenchent le problème.

Cause racine : Comportement de type fuite (tableaux non bornés, options autoload énormes, cron qui dérape) ou croissance des données.

Fix : Identifiez l’endpoint, profilez la mémoire, corrigez la croissance des données (nettoyage autoload) et placez des garde‑fous sur imports/rapports.

6) « WP-CLI marche, le site web plante »

Symptôme : Les commandes CLI réussissent ; les requêtes web échouent.

Cause racine : Différence de php.ini et de memory_limit entre CLI et FPM.

Fix : Ajoutez le tuning FPM/php.ini pour le web ; traitez le CLI comme un runtime distinct.

Deuxième petite blague, puis au travail : Mettre memory_limit à 2G sans mesurer, c’est comme réparer une fuite en achetant un sous‑sol plus grand.

Listes de contrôle / plan étape par étape

Récupération d’urgence (remettre le site en ligne sans l’aggraver)

  1. Confirmez le mode de panne. Fatal PHP vs OOMKilled du système vs timeout.
  2. Augmentez la limite effective dans la couche qui l’impose. Pour FPM : config du pool. Pour conteneurs : cgroup plus PHP.
  3. Rechargez, ne redémarrez pas, quand c’est possible. Pour réduire l’impact client.
  4. Réduisez la concurrence si vous êtes proche des limites hôtes. Baissez pm.max_children pour éviter un OOM complet du nœud.
  5. Capturez des preuves. Ligne de log avec les octets épuisés, endpoint et contexte plugin.

Stabilisation (rendre le comportement prévisible)

  1. Mesurez la distribution du RSS des workers. Utilisez ps pour obtenir les points hauts réels.
  2. Dimensionnez le pool FPM. Réglez pm.max_children sur la base mémoire, pas sur l’espoir.
  3. Définissez un memory_limit raisonnable. Valeurs typiques en production : 256M–512M selon la charge, mais seulement après mesure.
  4. Auditez les options autoload. Réduisez l’inflation mémoire de base.
  5. Vérifiez la taille d’OPcache. Évitez la famine du cache de code.

Corrections de cause racine (là où vous gagnez réellement)

  1. Localisez l’endpoint. Admin-ajax ? Rapports ? Import ? Recherche produit ?
  2. Testez la désactivation des plugins suspects. Un par un, avec rollback contrôlé.
  3. Optimisez l’accès aux données. Pagination, limiter les exports, éviter de charger des ensembles complets.
  4. Déplacez le travail lourd en asynchrone. Jobs d’arrière-plan plutôt que requêtes admin synchrones.
  5. Reconsidérez les contraintes d’hébergement. Si vous êtes sur du mutualisé et que vous tapez des plafonds invisibles, planifiez une migration.

FAQ

1) Est‑ce que « Allowed memory size exhausted » est toujours corrigé en augmentant memory_limit ?

Non. C’est corrigé en faisant en sorte que la requête consomme moins de mémoire que la limite. Augmenter la limite peut être une mesure d’urgence valide, mais les fuites et charges non bornées nécessitent des corrections de code ou de données.

2) Quelle est une valeur raisonnable de memory_limit pour WordPress en 2025 ?

256M est une base courante pour les sites non e‑commerce. 384M–512M est courant pour WooCommerce et les charges admin/rapports lourdes. Si vous avez besoin régulièrement de 1G, considérez cela comme un symptôme et enquêtez.

3) Pourquoi wp-config.php ne fonctionne pas parfois ?

Parce que PHP-FPM (ou l’hôte) peut imposer memory_limit avec php_admin_value ou la politique du fournisseur. WordPress ne peut demander des augmentations que si PHP l’autorise.

4) Pourquoi le fatal affiche des octets au lieu de mégaoctets ?

PHP rapporte la mémoire en octets. 128M = 134,217,728 octets ; 256M = 268,435,456 octets ; 512M = 536,870,912 octets. Utilisez cela pour identifier le vrai plafond.

5) Le site ne plante que pendant des imports. Dois‑je augmenter la mémoire en permanence ?

Préférez exécuter les imports en plus petits lots ou via un outil CLI avec une limite temporairement plus élevée. Des limites permanentes élevées augmentent l’impact des bugs et des pics de trafic.

6) Comment savoir si la limite du conteneur est le vrai problème ?

Si vous voyez des événements OOMKilled, des redémarrages de conteneur ou des logs noyau OOM sans fatals PHP, vous atteignez la limite cgroup/OS. Alignez la mémoire du conteneur, le memory_limit PHP et la concurrence FPM.

7) Est‑ce qu’OPcache peut provoquer des erreurs « memory exhausted » ?

L’épuisement d’OPcache est séparé du memory_limit de la requête PHP, mais il peut causer une instabilité et un effondrement des performances qui ressemblent à des pannes aléatoires. Dimensionnez OPcache selon votre empreinte de plugins/thèmes.

8) Dois‑je définir WP_MAX_MEMORY_LIMIT plus haut que WP_MEMORY_LIMIT ?

Oui, souvent. Les requêtes front‑end doivent être contraintes ; les tâches admin nécessitent légitimement plus de marge. Mais cela ne marche que si PHP l’autorise et si votre hôte dispose de la RAM nécessaire.

9) Que faire si je suis sur un hébergement mutualisé et que je ne peux pas changer memory_limit ?

Alors votre vraie limite est votre offre. Optimisez la charge (désactivez les plugins lourds, réduisez l’autoload bloat, batchifiez les imports), et planifiez une montée en gamme ou une migration si l’activité en dépend.

10) Augmenter pm.max_children est‑ce une bonne solution aux erreurs mémoire ?

Généralement non. Plus d’enfants augmente la consommation mémoire totale. Augmentez‑le seulement après avoir mesuré le RSS par worker et si vous avez un budget RAM disponible.

Prochaines étapes que vous pouvez faire aujourd’hui

  1. Décidez quel échec vous avez : fatal PHP memory_limit vs OOM du système/conteneur vs timeout.
  2. Trouvez la couche qui impose la limite : pool PHP-FPM, php.ini, limite conteneur ou cap d’hébergement.
  3. Augmentez la bonne limite, minimalement : suffisamment pour restaurer le service, pas assez pour masquer une fuite pendant des mois.
  4. Faites le calcul de concurrence : RSS par worker × max_children doit tenir dans la machine en laissant de la marge.
  5. Chassez le vrai coupable : plugins lourds, autoload bloat, rapports/imports non bornés ou comportement cron.

Si vous ne faites rien d’autre, faites ceci : arrêtez de considérer les paramètres mémoire WordPress comme faisant foi. La plateforme décide. Votre travail est de rendre cette décision explicite, mesurée et sûre.

← Précédent
Roulette du câble HDMI : identique à l’extérieur, différent à l’intérieur
Suivant →
OpenVPN sur Windows : problèmes du pilote TAP et comment les réparer

Laisser un commentaire