WordPress « Allowed memory size exhausted » : corrigez-le définitivement

Cet article vous a aidé ?

Cela arrive toujours au pire moment : vous cliquez sur « Mettre à jour » dans wp-admin, le spinner tourne, puis vous obtenez une erreur fatale liée à la mémoire. Ou l’administration se transforme en page blanche et votre téléphone sonne comme si vous aviez volontairement supprimé la base de données.

Ce problème n’est que rarement résolu en « ajoutant simplement plus de RAM ». Il se résout en comprenant la mémoire que WordPress est réellement autorisé à utiliser, ce que PHP utilise effectivement et ce qui la dévore en silence : plugins, traitement d’images, imports, tâches cron, et le thème occasionnel qui pense que la récursion est un mode de vie.

What the error really means (and what it doesn’t)

The classic message looks like:

Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes)

Translate it like an SRE:

  • « Allowed memory size » est le plafond de mémoire du processus PHP (memory_limit), pas la RAM physique du serveur.
  • Le nombre en bytes indique la limite au moment de l’échec (268,435,456 bytes = 256M).
  • Le « tried to allocate … » est la goutte d’eau finale, pas la quantité totale manquante. Il se peut que vous manquiez de 20 KB ou de 200 MB. Vous ne le savez pas encore.
  • Le lieu d’exécution importe : les requêtes d’admin, WP-CLI, cron, AJAX, REST et le traitement d’images peuvent chacun s’exécuter sous différentes SAPI/pools PHP avec des limites distinctes.

Ce que cela ne signifie pas :

  • Ça ne signifie pas automatiquement que WordPress « a besoin de plus de mémoire ». Parfois il faut moins de plugins, moins d’options autoloadées, ou éviter la construction de tableaux gigantesques à partir de requêtes non paginées.
  • Ce n’est pas une raison pour définir memory_limit = -1 sauf si vous aimez transformer de petits problèmes en incidents majeurs.
  • Ce n’est pas parce que vous avez plus de RAM serveur que le problème est réglé. Vous pouvez avoir 128 GB de RAM et limiter PHP à 128M, puis vous étonner que WooCommerce plante en cours de requête.

Voici la vérité opérationnelle : WordPress est une application PHP avec un écosystème de plugins qui peut et va dépasser des limites raisonnables à moins que vous ne mesuriez et n’appliquiez des règles. Votre travail consiste à rendre la limite appropriée et la charge de travail raisonnable.

Interesting facts and a little history

Ce ne sont pas des anecdotes de soirée. Elles expliquent pourquoi les modes d’échec sont si fréquents.

  1. Le memory_limit de PHP existe depuis PHP 4 comme garde-fou contre les scripts qui s’emballent en hébergement mutualisé. WordPress a grandi dans ce contexte.
  2. La « white screen of death » dans WordPress était historiquement causée par des erreurs PHP fatales avec l’affichage désactivé. L’épuisement de mémoire en est une des principales causes.
  3. WordPress définit deux constantes mémoire : WP_MEMORY_LIMIT (front-end) et WP_MAX_MEMORY_LIMIT (admin). Beaucoup de gens en modifient une et en supposent les effets sur l’autre.
  4. WooCommerce et les page builders ont alourdi l’admin : « admin » n’est plus quelques formulaires, mais une application monopage effectuant de lourdes requêtes API et manipulant de grands graphes d’objets.
  5. OPcache peut réduire le churn mémoire (moins de recompilations) mais il consomme aussi sa mémoire partagée. Un mauvais réglage peut provoquer des comportements « ça échoue seulement parfois ».
  6. Le traitement d’images s’est alourdi avec le temps à cause des images responsive et des multiples tailles par défaut. Un seul upload peut entraîner plusieurs redimenssionnements plus le parsing EXIF.
  7. Les autoloaders Composer et les bibliothèques PHP modernes sont entrés dans les plugins. C’est excellent pour le développement, mais parfois catastrophique pour la mémoire si des vendeurs sont inclus plusieurs fois.
  8. Certains hébergeurs exécutent des pools PHP-FPM séparés par site ou par utilisateur. Bonne isolation, mais cela veut dire que votre « j’ai changé php.ini » touche souvent le mauvais pool.
  9. Le cron WordPress n’est pas un vrai cron par défaut ; il est déclenché par le trafic. Cela signifie que les tâches lourdes peuvent se lancer au pire moment : juste quand un admin tente de mettre à jour des plugins.

Fast diagnosis playbook

Si vous voulez arrêter l’hémorragie rapidement, vous avez besoin d’un ordre déterministe de vérifications. N’éditez pas trois configs en espérant. Faites ceci :

1) Confirm where the request runs and what PHP config it uses

  • Si cela se produit dans wp-admin, vous êtes probablement en PHP-FPM via Nginx/Apache proxy, ou mod_php sur Apache.
  • Si cela se produit dans WP-CLI, vous utilisez le PHP CLI (ini différent, memory_limit différent).
  • Si cela se produit pendant un cron/import, cela peut s’exécuter sous PHP-FPM mais sur un endpoint différent ou même dans un pool différent.

2) Read the logs that contain the truth

  • Logs d’erreurs PHP-FPM (stack traces d’épuisement mémoire, nom du pool).
  • Log d’erreurs du serveur web (chemin de la requête, upstream, timeouts).
  • Journal de debug WordPress (si activé) pour le dernier code plugin/thème exécuté.

3) Measure real memory use per request

  • Si une requête monte jusqu’au plafond : vous avez une page lourde (souvent liée à un plugin).
  • Si la mémoire augmente au fil du temps across requests : vous pouvez avoir un pattern de fuite mémoire (plus courant avec des workers persistants + cache d’objets dans des variables statiques).

4) Apply the smallest safe mitigation

  • Augmentez memory_limit modérément (256M → 512M est courant pour des stacks admin complexes).
  • Augmentez seulement pour le pool/site qui en a besoin, pas pour tout le serveur.
  • Retestez l’action exacte qui échouait (mise à jour de plugin, upload média, génération de rapport).

5) Fix the underlying load

  • Désactivez ou remplacez le plugin gourmand en mémoire.
  • Corrigez le bloat des options autoloadées.
  • Paginez les requêtes, réduisez les widgets du tableau de bord, et corrigez les outils d’import/export.

Règle : l’ajustement mémoire est un pansement tant que vous n’avez pas prouvé que la charge est saine.

Root causes you can actually fix

Cause A: You changed the wrong knob

Il existe plusieurs « limites mémoire » en jeu :

  • PHP memory_limit : le vrai plafond. Défini dans php.ini, la config du pool, ou via des overrides runtime.
  • WP_MEMORY_LIMIT / WP_MAX_MEMORY_LIMIT : WordPress demande une limite mémoire, mais PHP peut refuser si la configuration est plus basse.
  • Valeurs du panneau d’hébergement : elles écrivent souvent dans un emplacement ini mais votre pool FPM charge un autre fichier.
  • Limites de conteneur (cgroups) : si vous êtes dans Docker/Kubernetes, le conteneur peut être limité même si PHP dit « 512M ».

Cause B: Plugin or theme builds massive arrays (often accidentally)

Schémas courants :

  • Charger tous les posts/users/orders sans pagination (« juste pour le dropdown »).
  • Exécuter des analytics coûteux en PHP au lieu de SQL.
  • Récupérer des API distantes et mettre en cache des réponses entières en mémoire.
  • Rendu récursif ou shortcodes imbriqués qui font exploser la taille du contenu.

Cause C: Autoloaded options bloat

WordPress charge toutes les options avec autoload = 'yes' à chaque requête. Si cet ensemble de lignes devient des mégaoctets de données sérialisées, chaque requête en paie le prix. L’admin paie plus parce qu’il fait plus. C’est le tueur silencieux des sites « ça marchait avant ».

Cause D: Media processing and large uploads

Le redimensionnement d’images peut allouer de grands buffers. Il en va de même pour la génération de vignettes PDF, le parsing EXIF, et les plugins « optimiser les images à l’upload ». Des pics de mémoire sont normaux ; des pics répétés atteignant votre plafond ne le sont pas.

Cause E: Cron collisions and background jobs

Si WP-Cron déclenche du travail lourd pendant une activité d’administration, vous avez une contention mémoire et une exhaustion des workers. L’erreur peut apparaître sur des pages d’admin non liées parce que le pool est sous tension et que les workers se recyclent au mauvais moment.

Cause F: PHP-FPM pool sized like a fantasy novel

Si chaque worker PHP-FPM peut utiliser jusqu’à 512M, et que vous autorisez 20 children, vous avez promis au noyau 10 GB de mémoire qu’il n’a peut‑être pas. Linux fera respecter la réalité avec du swap, des OOM kills et de la tristesse. Votre problème WordPress devient une panne serveur.

Cause G: OPcache misconfiguration

OPcache aide, mais un mauvais dimensionnement entraîne des redémarrages fréquents ou un thrash du cache. Cela peut amplifier les pics mémoire lors de la recompilation et augmenter la latence des requêtes, provoquant plus de workers concurrents (et donc plus d’utilisation mémoire).

Une idée paraphrasée de Werner Vogels (CTO d’Amazon) : Everything fails, so design systems that expect failure and recover quickly. Cet état d’esprit s’applique ici : concevez des limites qui empêchent un plugin de prendre tout le site en otage.

Practical tasks: commands, outputs, decisions (12+)

Ces tâches présument un serveur Linux typique avec Nginx + PHP-FPM ou Apache. Adaptez les chemins à votre distro. Chaque tâche inclut : commande, sortie d’exemple, ce que cela signifie, et la décision à prendre.

Task 1: Identify which PHP binary you’re using (CLI)

cr0x@server:~$ php -v
PHP 8.2.12 (cli) (built: Oct 10 2024 10:11:05) (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

Meaning: This is CLI PHP. WP-CLI uses this unless configured otherwise.

Decision: If the error occurs in WP-CLI (imports, updates), fix the CLI ini path and memory limit too—not just FPM.

Task 2: Find which ini files CLI PHP loads

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
                                  /etc/php/8.2/cli/conf.d/20-mysqli.ini

Meaning: This is where CLI memory_limit is coming from.

Decision: If CLI jobs fail, edit /etc/php/8.2/cli/php.ini (or add an override ini) rather than changing FPM settings and wondering why nothing changes.

Task 3: Check current CLI memory_limit

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

Meaning: CLI jobs are capped at 128M.

Decision: For WP-CLI heavy operations, set it higher (often 512M or 1024M), or use per-command overrides.

Task 4: Verify PHP-FPM service and version

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)
     Active: active (running) since Fri 2025-12-27 08:41:10 UTC; 2h 11min ago
       Docs: man:php-fpm8.2(8)
   Main PID: 1134 (php-fpm8.2)
      Tasks: 34 (limit: 18970)
     Memory: 612.3M

Meaning: PHP-FPM is running; memory here is total across workers.

Decision: If the service is restarting often or memory is huge, you likely have pool sizing issues or a memory hog request pattern.

Task 5: Locate the PHP-FPM pool config actually serving the site

cr0x@server:~$ grep -R "listen =" -n /etc/php/8.2/fpm/pool.d
/etc/php/8.2/fpm/pool.d/www.conf:41:listen = /run/php/php8.2-fpm.sock
/etc/php/8.2/fpm/pool.d/siteA.conf:33:listen = /run/php/php8.2-fpm-siteA.sock

Meaning: There are multiple pools. Your site might not be using www.

Decision: Identify the socket your vhost uses, then tune the correct pool. Editing the wrong pool is a classic “I swear I changed it” outage.

Task 6: Confirm Nginx is pointing to the expected FPM socket

cr0x@server:~$ sudo nginx -T 2>/dev/null | grep -n "fastcgi_pass" | head
218:        fastcgi_pass unix:/run/php/php8.2-fpm-siteA.sock;
401:        fastcgi_pass unix:/run/php/php8.2-fpm.sock;

Meaning: Different server blocks use different pools.

Decision: Apply memory_limit and pool sizing changes to the pool actually used by the WordPress vhost.

Task 7: Check FPM pool memory limit overrides

cr0x@server:~$ sudo grep -nE "php_admin_value\[memory_limit\]|php_value\[memory_limit\]" /etc/php/8.2/fpm/pool.d/siteA.conf
55:php_admin_value[memory_limit] = 256M

Meaning: The pool hard-caps PHP at 256M regardless of wp-config.php.

Decision: If admin actions exceed 256M, raise this value cautiously (e.g., 512M) and recalc FPM max_children to avoid OOM risk.

Task 8: Reload PHP-FPM safely after changes

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

Meaning: Reload applies config without dropping all connections (usually).

Decision: Prefer reload to restart in production. If reload fails, check syntax and logs before escalating to restart.

Task 9: Confirm memory_limit seen by FPM via a temporary endpoint

cr0x@server:~$ printf '%s\n' '/dev/null
cr0x@server:~$ curl -sS http://127.0.0.1/mem.php
256M

Meaning: The web-executed PHP sees 256M.

Decision: If you expected 512M and got 256M, you’re still editing the wrong config file, the wrong pool, or caching/proxying the wrong vhost.

Task 10: Inspect PHP-FPM slowlog and error log for memory exhaustion traces

cr0x@server:~$ sudo tail -n 30 /var/log/php8.2-fpm.log
[27-Dec-2025 10:42:18] WARNING: [pool siteA] child 20211, script '/var/www/siteA/public/wp-admin/admin-ajax.php' (request: "POST /wp-admin/admin-ajax.php") executing too slow (5.123 sec), logging
[27-Dec-2025 10:42:18] PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 65536 bytes) in /var/www/siteA/public/wp-content/plugins/some-plugin/includes/report.php on line 812

Meaning: The failing endpoint and offending plugin file are named. This is gold.

Decision: Don’t just raise memory. Investigate the plugin action (report generation via AJAX) and decide whether to disable, patch, or change its settings.

Task 11: Disable plugins without wp-admin (WP-CLI)

cr0x@server:~$ cd /var/www/siteA/public
cr0x@server:~$ sudo -u www-data wp plugin list --status=active
+----------------------+----------+-----------+---------+
| name                 | status   | update    | version |
+----------------------+----------+-----------+---------+
| woocommerce          | active   | none      | 8.5.2   |
| some-plugin          | active   | none      | 3.1.0   |
| cache-plugin         | active   | available | 2.9.1   |
+----------------------+----------+-----------+---------+
cr0x@server:~$ sudo -u www-data wp plugin deactivate some-plugin
Plugin 'some-plugin' deactivated.

Meaning: You can recover admin access without clicking around in a broken UI.

Decision: If deactivating stops memory exhaustion, you’ve isolated the culprit. Keep it off until you can reproduce in staging and fix properly.

Joke 1: Disabling a plugin to fix production feels like turning off the smoke alarm because the kitchen’s on fire. It works, but please also stop the fire.

Task 12: Check WordPress memory constants (wp-config.php)

cr0x@server:~$ grep -nE "WP_MEMORY_LIMIT|WP_MAX_MEMORY_LIMIT" /var/www/siteA/public/wp-config.php
91:define('WP_MEMORY_LIMIT', '256M');
92:define('WP_MAX_MEMORY_LIMIT', '512M');

Meaning: WordPress is requesting 512M for admin.

Decision: If PHP-FPM is still at 256M, raise FPM’s memory_limit. If PHP-FPM is already at 512M and you still crash, fix the workload.

Task 13: Detect autoloaded options bloat in MySQL

cr0x@server:~$ mysql -N -e "SELECT ROUND(SUM(LENGTH(option_value))/1024/1024,2) AS autoload_mb FROM wp_options WHERE autoload='yes';"
8.74

Meaning: Nearly 9MB of autoloaded options are loaded on every request. That’s not a rounding error.

Decision: Anything above ~1–2MB is worth investigating. Above ~5MB, expect performance and memory pain. Find the biggest offenders and stop autoloading them.

Task 14: Find the worst autoload offenders

cr0x@server:~$ mysql -N -e "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;"
some_plugin_cache 3.12
builder_global_settings 1.47
woocommerce_sessions 0.88
theme_mods_mytheme 0.62

Meaning: A few options dominate the footprint.

Decision: For options that don’t need to be autoloaded, flip autoload to ‘no’ and ensure the plugin can handle it. If it can’t, replace the plugin or patch it.

Task 15: Flip autoload off for a specific option (carefully)

cr0x@server:~$ mysql -e "UPDATE wp_options SET autoload='no' WHERE option_name='some_plugin_cache';"
cr0x@server:~$ mysql -N -e "SELECT option_name, autoload FROM wp_options WHERE option_name='some_plugin_cache';"
some_plugin_cache	no

Meaning: The option will no longer be loaded on every request.

Decision: Test admin flows that depended on it. If anything breaks, revert and handle differently (plugin setting, cache backend, or replacement).

Task 16: Inspect PHP-FPM process memory in the real world

cr0x@server:~$ ps -o pid,pmem,rss,cmd -C php-fpm8.2 --sort=-rss | head
  PID %MEM   RSS CMD
20211  2.6 214336 php-fpm: pool siteA
20219  2.5 208912 php-fpm: pool siteA
20205  1.8 146220 php-fpm: pool siteA

Meaning: RSS shows real resident memory. Workers are around ~200MB each right now.

Decision: Use this to size pm.max_children. If each child is ~200MB and you can spare 2GB for PHP workers, don’t run 20 children.

Task 17: Check cgroup/container memory limits (if applicable)

cr0x@server:~$ cat /sys/fs/cgroup/memory.max 2>/dev/null || true
1073741824

Meaning: The process is capped at 1GB by cgroups (value is bytes). That’s the ceiling for everything in the container.

Decision: If you set PHP to 512M and allow multiple workers, you’ll hit container OOM. Adjust container limits or worker counts.

Task 18: Verify OPcache sizing and behavior

cr0x@server:~$ php -r 'print_r(opcache_get_status(false)["memory_usage"]);'
Array
(
    [used_memory] => 78120384
    [free_memory] => 26345472
    [wasted_memory] => 4128768
    [current_wasted_percentage] => 4.72
)

Meaning: OPcache has limited free memory; wasted is moderate.

Decision: If free memory is near zero and wasted climbs, increase opcache.memory_consumption and/or tune revalidate settings. If OPcache resets frequently, your request latency and peak concurrency can rise, increasing memory pressure.

Three corporate mini-stories from the trenches

Mini-story 1: The incident caused by a wrong assumption

L’entreprise avait une installation WordPress « simple » : site marketing, quelques landing pages et un blog. Puis ils ont ajouté WooCommerce « juste pour quelques produits ». Personne n’a changé le niveau d’hébergement parce que c’était « juste un plugin ».

Deux semaines plus tard, la finance a demandé un rapport de commandes. Un responsable a cliqué sur « Export CSV » depuis l’admin. La page admin a bloqué, puis planté avec l’erreur fatale d’épuisement de mémoire. Ils ont réessayé. Même résultat. Puis encore, parce que les humains sont cohérents ainsi.

L’ingénieur d’astreinte a augmenté WP_MAX_MEMORY_LIMIT à 512M, mais le plantage a continué. Ils l’ont monté à 1024M. Toujours pareil. Ils en ont conclu que la VM était « trop petite » et ont demandé une machine plus grosse.

Le vrai problème était que PHP-FPM avait un override au niveau du pool : php_admin_value[memory_limit] = 256M provenant de la migration depuis un hébergement mutualisé. WordPress demandait poliment plus de mémoire et se faisait poliment refuser.

Une fois l’équipe ayant corrigé la config du pool et augmenté la limite à 512M, l’export a réussi — mais a mis un temps fou et a gonflé la mémoire des workers. Cela a mené à la seconde leçon : la méthode d’export chargeait toutes les commandes dans des tableaux PHP. Ils l’ont remplacée par une exportation paginée qui stream les lignes. Les incidents mémoire ont cessé.

Mini-story 2: The optimization that backfired

Une autre organisation a voulu « optimiser » en durcissant les limites mémoire sur tous les pools PHP. La logique semblait raisonnable : des limites basses empêchent les scripts qui s’emballent. Ils ont fixé memory_limit à 128M partout et se sont félicités d’avoir imposé la discipline.

Pendant un mois tout a semblé aller bien. Puis une campagne saisonnière a été lancée et les éditeurs ont uploadé beaucoup d’images haute résolution. WordPress a commencé à générer plusieurs tailles d’images, quelques plugins ont fait de la « compression intelligente », et des previews PDF ont été générées pour des media kits.

Du jour au lendemain, les uploads ont échoué de façon intermittente avec des erreurs d’épuisement mémoire. Intermittent est le mot clé : les petites images passaient, les grosses échouaient. Le support ne pouvait pas reproduire sauf avec les mêmes images exactes.

L’« optimisation » a augmenté le taux d’échec parce qu’elle a supprimé la capacité d’absorption nécessaire pour les workloads légitimes. Ils ont finalement relevé la mémoire du pool de traitement média à 512M et externalisé les transformations lourdes vers un worker en file d’attente avec plus de marge.

Ils ont conservé la limite basse sur les pools front-end. Cette partie était correcte. Le problème était de croire qu’un seul nombre convient à tous les workloads.

Mini-story 3: The boring but correct practice that saved the day

Une grande entreprise gère des dizaines de sites WordPress derrière des pools Nginx et PHP-FPM standardisés. Rien de sophistiqué. La sauce secrète était ennuyeuse : pools par site, limites explicites et métriques sur le RSS des workers.

Quand un site a commencé à lancer des erreurs d’épuisement mémoire après une mise à jour de plugin, l’astreinte n’a pas débattu des heures sur Slack. Ils ont consulté la distribution RSS récente du pool et ont vu que la mémoire des workers avait doublé après la mise à jour. Cela a réduit la recherche de « WordPress est cassé » à « ce plugin a changé de comportement ».

Ils ont rollbacké la version du plugin (également ennuyeux), restauré le service, puis reproduit le problème en staging avec le même jeu de données. Le plugin mettait en cache une grosse réponse d’API dans une option autoloadée — donc chaque requête en subissait le coût.

Comme ils disposaient déjà d’une checklist pour le « bloat autoload », ils l’ont repéré rapidement, corrigé et mis en place un garde-fou : une vérification automatisée qui alerte quand les options autoloadées dépassent un seuil.

Ce n’était pas glorieux. Mais cela a évité une bagarre à 3 h du matin. C’est le type de succès qu’on n’apprécie qu’après avoir connu l’inverse.

Common mistakes: symptom → root cause → fix

1) Symptom: You set WP_MEMORY_LIMIT but the error still shows the old byte value

Root cause: PHP is capped lower than WordPress constants (pool override, php.ini for FPM, or hosting panel mismatch).

Fix: Confirm memory_limit via a web endpoint (Task 9) and change the correct FPM pool config (Task 7), then reload FPM (Task 8).

2) Symptom: WP-CLI commands fail with memory exhaustion, but wp-admin is fine

Root cause: CLI php.ini has a lower memory_limit than FPM.

Fix: Check php --ini and php -r 'ini_get(...)' (Tasks 2–3). Raise CLI memory_limit or use php -d memory_limit=... for specific jobs.

3) Symptom: Only media uploads fail; regular admin pages work

Root cause: Image/PDF processing spikes memory; plugins add extra transforms.

Fix: Increase memory limit for the pool handling uploads; reduce image optimization aggressiveness; offload transforms; verify post_max_size and upload_max_filesize are reasonable (not covered by this error but often co-occurs).

4) Symptom: Random admin pages die after “a while,” especially under traffic

Root cause: FPM pool overcommitted; too many children; swapping; OOM kills; or memory growth across worker lifetime.

Fix: Measure worker RSS (Task 16), set pm.max_children based on memory budget, enable pm.max_requests to recycle workers, and watch for a plugin that accumulates memory in persistent workers.

5) Symptom: After enabling a cache plugin, memory errors get worse

Root cause: Object caching in PHP arrays, autoload bloat, or caching full page fragments in memory per request.

Fix: Inspect autoload size (Tasks 13–15), configure a proper external object cache backend if needed, and avoid caching entire datasets in options.

6) Symptom: Increasing memory_limit fixed it… for a week

Root cause: Underlying data growth or a slow leak pattern (autoloaded options growing, logs stored in options, transient bloat, plugin update).

Fix: Trend autoloaded options size, worker RSS distribution, and error counts. Identify growing tables/options and purge/repair the source.

7) Symptom: You set memory_limit very high and now the server is unstable

Root cause: You raised per-process caps without reducing concurrency. The kernel can’t pay the promised memory bill.

Fix: Reduce FPM pm.max_children, set realistic memory_limit, and use queues for heavy jobs. Unlimited memory is a performance anti-pattern wearing a trench coat.

Joke 2: Setting memory_limit = -1 is like removing the speedometer because you don’t like speeding tickets. The wall still exists.

Checklists / step-by-step plan (permanent fixes)

Step-by-step plan: stabilize, then make it stay fixed

Phase 1: Get wp-admin back (15–30 minutes)

  1. Find the failing endpoint and culprit in PHP-FPM logs (Task 10). If you don’t know what failed, you’re guessing.
  2. Disable the suspected plugin via WP-CLI (Task 11) or temporarily move its directory out of wp-content/plugins.
  3. Confirm actual memory_limit used by the site with the mem.php check (Task 9), then delete that file.
  4. Raise pool memory_limit conservatively (256M → 512M) if needed (Task 7), reload FPM (Task 8).

Phase 2: Make memory predictable (same day)

  1. Measure worker RSS and set pm.max_children using reality, not hope (Task 16).
  2. Add worker recycling with pm.max_requests (start around 300–1000 depending on code stability). This limits long-lived growth patterns.
  3. Stop autoload bloat: measure size (Task 13), list offenders (Task 14), change autoload for non-critical blobs (Task 15), and fix the plugin behavior.
  4. Separate pools for heavy workloads (admin/media/import) if you can. Different caps, different concurrency, fewer surprise interactions.

Phase 3: Fix the workload (week 1)

  1. Reproduce in staging with production-like data. Most “it only fails in prod” memory issues are data-size issues.
  2. Replace or patch the memory hog. Plugins that load everything into memory should be treated like a production risk, not a feature.
  3. Stream exports/imports: chunk reads, paginate queries, write output incrementally, and avoid building giant arrays.
  4. Move heavy jobs off the request path using real cron and a queue/worker approach. Requests should be quick; jobs can be heavy.

Checklist: PHP-FPM pool sizing that won’t OOM your box

  • Measure typical and peak RSS per worker (ps, Task 16).
  • Decide a memory budget for PHP workers (e.g., 40–60% of RAM after DB, cache, OS).
  • Compute pm.max_children ≈ budget / peak RSS (round down).
  • Set pm = dynamic with sane pm.start_servers, pm.min_spare_servers, pm.max_spare_servers.
  • Set pm.max_requests to recycle.
  • Keep memory_limit high enough for legitimate admin actions, but not so high one request can starve the host.

Checklist: WordPress-specific hygiene that prevents memory blowups

  • Keep autoloaded options lean; alert when autoload MB grows past a threshold.
  • Audit plugins quarterly: remove abandoned ones, replace heavy ones, and delete feature-overlap.
  • Use WP-CLI for controlled bulk operations with explicit memory limits.
  • Turn WP-Cron into real cron so jobs run on schedule, not during user requests.
  • Watch admin-ajax usage; it’s where “just a small report” turns into a 500MB request.

FAQ

1) Is “Allowed memory size exhausted” a WordPress limit or a PHP limit?

C’est une limite PHP. WordPress peut demander plus de mémoire via des constantes, mais c’est PHP qui applique le plafond effectif.

2) I set define('WP_MEMORY_LIMIT','512M'). Why does it still fail?

Parce que PHP est toujours plafonné plus bas (override de pool, php.ini pour FPM, ou limite de conteneur). Vérifiez via un endpoint web (Task 9) et corrigez le pool approprié (Tasks 5–7).

3) What’s a sane memory_limit for WordPress admin?

Pour un site simple : 256M suffit souvent. Pour WooCommerce/page builders/administration lourde : 512M est courant. Au‑delà, considérez-le comme un symptôme et recherchez le bloat.

4) Should I set WP_MAX_MEMORY_LIMIT higher than WP_MEMORY_LIMIT?

Oui. Les requêtes front-end devraient être plus légères et prévisibles. L’admin peut légitimement nécessiter plus pour les mises à jour, médias, exports et tableaux de bord.

5) Can OPcache cause memory exhaustion errors?

OPcache n’entre pas dans le memory_limit de la même façon (il utilise de la mémoire partagée), mais de mauvais réglages d’OPcache peuvent augmenter la latence et la concurrence, augmentant indirectement la pression mémoire totale des workers PHP.

6) If I increase memory_limit, can that make performance worse?

Oui, si vous n’ajustez pas la concurrence. Des plafonds par worker plus élevés avec le même pm.max_children peuvent pousser l’hôte au swapping ou à l’OOM. Calibrez le système globalement.

7) Why does it only happen on certain admin pages?

Ces pages déclenchent des chemins de code plus lourds : génération de rapports, opérations par lots, transformations média, ou plugins qui interrogent trop de données. Les logs (Task 10) révèlent généralement le fichier responsable.

8) What’s the fastest safe way to regain access if wp-admin is dead?

Désactivez le plugin suspect via WP-CLI (Task 11) ou déplacez son répertoire. Puis corrigez la cause racine avant de le réactiver.

9) Can database bloat cause PHP memory exhaustion?

Indirectement, oui. De gros blobs d’options (surtout autoloadées) et des requêtes non bornées peuvent ramener de grands jeux de résultats en mémoire PHP. Mesurez la taille autoload (Task 13) et corrigez les coupables (Task 14).

10) How do I prevent this from coming back after plugin updates?

Utilisez des tests en staging avec des données réelles, surveillez les tendances RSS des workers, alertez sur la croissance des autoload MB et appliquez une gouvernance des plugins. La phase « installer n’importe quoi » s’arrête quand la production commence.

Conclusion: what to do next

Si vous voulez résoudre ça définitivement, cessez de traiter l’épuisement mémoire comme un seul réglage. C’est un comportement système.

  1. Aujourd’hui : Utilisez les logs pour identifier l’endpoint et le plugin en échec, vérifiez le memory_limit réel pour le web et le CLI, et stabilisez avec une augmentation conservatrice si nécessaire.
  2. Cette semaine : Mesurez le RSS des workers, dimensionnez la concurrence PHP-FPM selon le budget mémoire, recyclez les workers et nettoyez le bloat d’options autoloadées.
  3. En continu : Traitez les changements de plugins comme des changements de code — testez, mesurez et revenez en arrière rapidement. Ajoutez des alertes pour la croissance de l’autoload et les taux d’erreurs mémoire.

Faites cela, et « Allowed memory size exhausted » redeviendra ce qu’il devrait être : une garde‑fou rare, pas un événement récurrent du calendrier.

← Précédent
WordPress 403 Forbidden : diagnostiquer et corriger permissions, règles WAF et blocages
Suivant →
DMARC : quarantaine vs rejet — quand basculer et comment le déployer en toute sécurité

Laisser un commentaire