WordPress ‘Allowed memory size exhausted’: solución definitiva

¿Te fue útil?

Siempre sucede en el peor momento: haces clic en “Actualizar” en wp-admin, el spinner gira y luego obtienes un error fatal sobre la memoria. O el panel de administración se convierte en una página blanca y tu teléfono empieza a sonar como si hubieras borrado la base de datos a propósito.

Este problema rara vez se soluciona simplemente “añadiendo más RAM”. Se soluciona entendiendo qué memoria se le permite realmente usar a WordPress, qué está usando PHP en realidad y qué la está consumiendo en silencio: plugins, procesamiento de imágenes, importaciones, trabajos cron y algún tema ocasional que considera la recursión un estilo de vida.

Qué significa realmente el error (y qué no significa)

El mensaje clásico se ve así:

Error fatal: Tamaño de memoria permitido de 268435456 bytes agotado (se intentó asignar 20480 bytes)

Trádúcelo como un SRE:

  • “Allowed memory size” es el tope de memoria del proceso PHP (memory_limit), no la RAM física del servidor.
  • El número en bytes te indica el límite en el momento del fallo (268,435,456 bytes = 256M).
  • El “se intentó asignar …” es la última gota, no el total que falta. Podrías quedarte corto por 20 KB o por 200 MB. Aún no lo sabes.
  • Dónde ocurre importa: las solicitudes de administración, WP-CLI, cron, AJAX, REST y el procesamiento de imágenes pueden ejecutarse bajo diferentes SAPI/pools de PHP con límites distintos.

Lo que no significa:

  • No significa automáticamente que WordPress “necesite más memoria”. A veces necesita menos plugins, menos opciones autoload, o menos arrays gigantes construidos a partir de consultas sin paginar.
  • No significa que debas poner memory_limit = -1 a menos que disfrutes convertir pequeños problemas en incidentes mayores.
  • No significa que más RAM física arregle el problema. Puedes tener 128 GB de RAM y aún así limitar PHP a 128M, y luego preguntarte por qué WooCommerce muere a mitad de petición.

Aquí está la verdad operativa: WordPress es una aplicación PHP con un ecosistema de plugins que puede y va a exceder límites razonables a menos que midas y hagas cumplir dichos límites. Tu trabajo es hacer el límite apropiado y sanear la carga de trabajo.

Datos interesantes y algo de historia

Esto no es trivia de noche de bar. Explica por qué los modos de fallo son tan comunes.

  1. El memory_limit de PHP existe desde PHP 4 como una protección contra scripts descontrolados en hosting compartido. WordPress creció en ese mundo.
  2. La “pantalla blanca de la muerte” en WordPress solía ser causada por errores fatales de PHP con display deshabilitado. La falta de memoria es una de las causas principales.
  3. WordPress define dos constantes de memoria: WP_MEMORY_LIMIT (frontend) y WP_MAX_MEMORY_LIMIT (admin). Mucha gente define una y asume que ambas cambian.
  4. WooCommerce y los page builders cambiaron la carga del admin: el “admin” dejó de ser unos pocos formularios y se convirtió en una aplicación de una sola página que hace llamadas API pesadas y maneja grafos de objetos grandes.
  5. OPcache puede reducir la churn de memoria (menos recompilaciones) pero también consume memoria compartida. Ajustarlo mal puede producir comportamientos extraños de “falla solo a veces”.
  6. El procesamiento de imágenes se volvió más pesado con imágenes «responsive» y múltiples tamaños por defecto. Una subida puede implicar muchas redimensiones, además del parseo EXIF.
  7. Los autoloaders de Composer y librerías PHP modernas se colaron en plugins. Genial para ingeniería, ocasionalmente terrible para la memoria si los vendors se empacan repetidamente.
  8. Algunos hosts ejecutan pools PHP-FPM separados por sitio o usuario. Eso es buena aislamiento, pero significa que tu “cambié php.ini” a menudo afecta el pool equivocado.
  9. El cron de WordPress no es un cron real por defecto; se activa con tráfico. Eso significa que trabajos pesados pueden ejecutarse en el peor momento posible: justo cuando un admin intenta actualizar plugins.

Guía rápida de diagnóstico

Si quieres dejar de sangrar rápidamente, necesitas un orden determinista de comprobaciones. No empieces editando tres configuraciones a la vez esperando suerte. Haz esto:

1) Confirma dónde se ejecuta la petición y qué configuración PHP usa

  • Si ocurre en wp-admin, probablemente estás alcanzando PHP-FPM vía proxy Nginx/Apache, o mod_php en Apache.
  • Si ocurre en WP-CLI, estás usando PHP CLI (ini diferente, límite de memoria diferente).
  • Si ocurre durante cron/import, puede ejecutarse bajo PHP-FPM pero en un endpoint distinto o incluso en otro pool.

2) Lee los logs que contienen la verdad

  • Log de errores de PHP-FPM (trazas de stack por agotamiento de memoria, nombre del pool).
  • Log de errores del servidor web (ruta de la petición, upstream, timeouts).
  • Log de depuración de WordPress (si está habilitado) para ver el último código ejecutado del plugin/tema.

3) Mide el uso real de memoria por petición

  • Si una petición alcanza el tope: tienes una página pesada (a menudo provocada por un plugin).
  • Si la memoria crece con el tiempo a través de peticiones: puede haber un patrón de fuga (más común con workers persistentes + objetos cacheados en variables estáticas).

4) Aplica la mitigación más pequeña y segura

  • Sube memory_limit moderadamente (256M → 512M es común para stacks administrativos complejos).
  • Aumenta solo para el pool/sitio que lo necesita, no para todo el servidor.
  • Vuelve a probar la acción exacta que fallaba (actualización de plugin, subida de medios, generación de informe).

5) Arregla la carga subyacente

  • Desactiva o reemplaza el plugin que consume memoria.
  • Arregla la hinchazón de opciones autoload.
  • Paginar consultas, reducir widgets del dashboard y mejorar herramientas de importación/exportación.

Regla: el ajuste de memoria es un vendaje hasta que pruebes que la carga de trabajo está sana.

Causas raíz que puedes arreglar

Causa A: Cambiaste el control equivocado

Hay múltiples “límites de memoria” en juego:

  • PHP memory_limit: el tope real. Se establece en php.ini, en la configuración del pool o mediante overrides en tiempo de ejecución.
  • WP_MEMORY_LIMIT / WP_MAX_MEMORY_LIMIT: WordPress solicita un límite, pero PHP puede negarse si está configurado a un valor inferior.
  • Valores del panel de hosting: a menudo escriben en una ubicación ini, pero tu FPM puede cargar otro archivo.
  • Límites de contenedores (cgroups): si estás en Docker/Kubernetes, el contenedor puede estar limitado aunque PHP diga “512M”.

Causa B: Plugin o tema construye arrays masivos (a menudo sin querer)

Patrones comunes:

  • Cargar todos los posts/usuarios/pedidos sin paginar (“solo para el dropdown”).
  • Ejecutar analíticas costosas en PHP en lugar de en SQL.
  • Consumir APIs remotas y cachear respuestas enteras en memoria.
  • Renderizado recursivo o shortcodes anidados que explotan el tamaño del contenido.

Causa C: Hinchazón de opciones autoload

WordPress carga todas las opciones con autoload = 'yes' en cada petición. Si ese conjunto de filas se vuelve megabytes de basura serializada, cada petición lo paga. El admin paga más porque realiza más trabajo. Este es el asesino silencioso en sitios “que antes funcionaban”.

Causa D: Procesamiento de medios y subidas grandes

Redimensionar imágenes puede asignar buffers grandes. También lo hacen la generación de miniaturas PDF, el parseo EXIF y plugins que “optimizan imágenes al subir”. Los picos de memoria son normales; los picos repetidos que alcanzan tu tope no lo son.

Causa E: Colisiones de cron y trabajos en segundo plano

Si WP-Cron dispara trabajo pesado durante la actividad administrativa, tienes contención de memoria y agotamiento de workers. El error puede aparecer en páginas administrativas no relacionadas porque el pool está bajo estrés y los workers se reciclan en momentos malos.

Causa F: Pool PHP-FPM con tamaño de fantasía

Si cada worker de PHP-FPM puede usar hasta 512M y permites 20 children, le prometiste al kernel 10 GB de memoria que quizá no tiene. Linux impondrá la realidad con swapping, OOM kills y tristeza. Tu problema de memoria de WordPress se convierte en una caída del servidor.

Causa G: Configuración incorrecta de OPcache

OPcache ayuda, pero dimensionarlo mal lleva a reinicios frecuentes o thrash del caché. Eso puede amplificar picos de memoria durante la recompilación y aumentar la latencia de peticiones, provocando más workers concurrentes (y por tanto más uso de memoria).

Una idea parafraseada de Werner Vogels (CTO de Amazon): Everything fails, so design systems that expect failure and recover quickly. Esa mentalidad aplica aquí: diseña límites que impidan que un plugin tumbe todo el sitio.

Tareas prácticas: comandos, salidas, decisiones (12+)

Estas tareas asumen un servidor Linux típico con Nginx + PHP-FPM o Apache. Ajusta rutas para tu distro. Cada tarea incluye: comando, salida de ejemplo, qué significa y qué decisión tomar.

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.

Broma 1: Desactivar un plugin para arreglar producción se siente como apagar el detector de humo porque la cocina está en llamas. Funciona, pero por favor también apaga el fuego.

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.

Tres micro-historias corporativas desde las trincheras

Micro-historia 1: El incidente causado por una suposición equivocada

La empresa tenía una instalación “simple” de WordPress: sitio de marketing, algunas landing pages y un blog. Luego añadieron WooCommerce “solo para unos pocos productos”. Nadie cambió el plan de hosting porque era “solo un plugin”.

Dos semanas después, finanzas pidió un informe de pedidos. Un gestor bienintencionado hizo clic en “Exportar CSV” desde el admin. La página colgó y luego se estrelló con el error fatal de agotamiento de memoria. Intentaron de nuevo. Mismo resultado. Luego lo intentaron otra vez, porque los humanos son consistentes así.

El ingeniero on-call aumentó WP_MAX_MEMORY_LIMIT a 512M, pero el fallo continuó. Lo subieron a 1024M. Seguía fallando. Concluyeron que el servidor era “demasiado pequeño” y pidieron una VM más grande.

El verdadero problema era que PHP-FPM tenía un override a nivel de pool php_admin_value[memory_limit] = 256M de la migración inicial desde hosting compartido. WordPress pedía más memoria y PHP se lo ignoraba cortésmente.

Cuando el equipo arregló el config del pool correcto y subió el límite a 512M, la exportación tuvo éxito—pero tardó una eternidad y disparó la memoria de los workers. Eso llevó a la segunda lección: el método de exportación cargaba todos los pedidos en arrays PHP. Luego lo reemplazaron por un job de exportación paginado que transmitía filas. La memoria dejó de ser un incidente recurrente.

Micro-historia 2: La optimización que salió mal

Otra organización decidió “optimizar” apretando los límites de memoria en todos los pools PHP. La lógica sonaba razonable: límites más bajos previenen scripts descontrolados. Pusieron memory_limit a 128M en todas partes y se felicitaron por imponer disciplina.

Durante un mes todo parecía bien. Luego lanzaron una campaña estacional y los editores subieron muchas imágenes de alta resolución. WordPress empezó a generar múltiples tamaños, un par de plugins hicieron “compresión inteligente” y se generaron vistas previas PDF para kits de medios.

De repente las subidas fallaban de forma intermitente por agotamiento de memoria. Intermitente es la palabra clave: imágenes pequeñas funcionaban, las grandes morían. El equipo de soporte no podía reproducirlo a menos que usaran las mismas imágenes exactas.

La “optimización” aumentó la tasa de fallos porque eliminó la capacidad de ráfaga necesaria para cargas legítimas. Finalmente subieron la memoria para el pool de procesamiento de medios a 512M y externalizaron las transformaciones pesadas a un worker en cola con más margen.

Mantuvieron el límite más bajo en pools frontend. Esa parte fue correcta. El error fue asumir que un número sirve para todas las cargas de trabajo.

Micro-historia 3: La práctica aburrida pero correcta que salvó el día

Una empresa más grande ejecutaba docenas de sitios WordPress detrás de pools Nginx y PHP-FPM estandarizados. Nada especial. La receta secreta fue aburrida: pools por sitio, límites explícitos y métricas sobre RSS de los workers.

Cuando un sitio empezó a tirar errores de memoria tras una actualización de plugin, el on-call no lo debatió horas en Slack. Comprobaron la distribución reciente de RSS del pool y vieron que la memoria de los workers se había duplicado después de la actualización. Eso acotó la búsqueda de “WordPress está roto” a “este plugin cambió comportamiento”.

Revirtieron la versión del plugin (también aburrido), restauraron el servicio y luego reprodujeron el problema en staging con el mismo dataset. El plugin cacheaba una gran respuesta API en una opción autoload—así que cada petición la cargaba.

Como ya tenían una checklist para “autoload bloat”, lo detectaron rápido, lo arreglaron e implementaron un guardián: una comprobación automatizada que alerta cuando las opciones autoload superan un umbral.

No les dio premios. Evitó una pelea a las 3 a.m. Ese es el éxito que solo aprecias después de haber vivido lo contrario.

Errores comunes: síntoma → causa raíz → solución

1) Síntoma: Definiste WP_MEMORY_LIMIT pero el error sigue mostrando el valor antiguo en bytes

Causa raíz: PHP está limitado a un valor inferior que las constantes de WordPress (override del pool, php.ini de FPM o desajuste del panel de hosting).

Solución: Confirma memory_limit vía un endpoint web (Task 9) y cambia el config del pool FPM correcto (Task 7), luego recarga FPM (Task 8).

2) Síntoma: Los comandos WP-CLI fallan por agotamiento de memoria, pero wp-admin funciona

Causa raíz: php.ini CLI tiene un memory_limit inferior al de FPM.

Solución: Revisa php --ini y php -r 'ini_get(...)' (Tasks 2–3). Aumenta el memory_limit del CLI o usa php -d memory_limit=... para tareas puntuales.

3) Síntoma: Solo fallan las subidas de medios; las páginas administrativas normales funcionan

Causa raíz: El procesamiento de imágenes/PDF produce picos de memoria; plugins añaden transformaciones extra.

Solución: Aumenta el límite para el pool que maneja subidas; reduce la agresividad de optimización de imágenes; externaliza transformaciones; verifica post_max_size y upload_max_filesize (no cubierto por este error pero a menudo va ligado).

4) Síntoma: Páginas administrativas mueren aleatoriamente después de “un rato”, especialmente bajo tráfico

Causa raíz: Pool FPM sobredimensionado; demasiados children; swapping; OOM kills; o crecimiento de memoria durante la vida del worker.

Solución: Mide RSS de workers (Task 16), ajusta pm.max_children según presupuesto de memoria, habilita pm.max_requests para reciclar workers y busca un plugin que acumule memoria en workers persistentes.

5) Síntoma: Tras habilitar un plugin de caché, los errores de memoria empeoran

Causa raíz: Caché de objetos en arrays PHP, autoload bloat o cachear fragmentos de página enteros en memoria por petición.

Solución: Inspecciona tamaño de autoload (Tasks 13–15), configura un backend de object cache externo si hace falta y evita cachear datasets enteros en options.

6) Síntoma: Aumentar memory_limit lo arregló… por una semana

Causa raíz: Crecimiento de datos subyacente o patrón de fuga lento (opciones autoload en aumento, logs guardados en options, transients inflados, actualización de plugin).

Solución: Haz trending del tamaño de autoload, la distribución RSS de workers y el conteo de errores. Identifica tablas/opciones que crecen y purga/repara la fuente.

7) Síntoma: Pusiste memory_limit muy alto y ahora el servidor es inestable

Causa raíz: Subiste los topes por proceso sin reducir la concurrencia. El kernel no puede pagar la factura de memoria prometida.

Solución: Reduce pm.max_children, establece un memory_limit realista y usa colas para trabajos pesados. La memoria ilimitada es un antipatrón de rendimiento con disfraz.

Broma 2: Poner memory_limit = -1 es como quitar el velocímetro porque no te gustan las multas por exceso de velocidad. El muro sigue ahí.

Listas de comprobación / plan paso a paso (soluciones permanentes)

Plan paso a paso: estabilizar, luego hacer que se mantenga

Fase 1: Recuperar wp-admin (15–30 minutos)

  1. Localiza el endpoint que falla y el culpable en los logs de PHP-FPM (Task 10). Si no sabes qué falló, estás adivinando.
  2. Desactiva el plugin sospechoso vía WP-CLI (Task 11) o mueve temporalmente su directorio fuera de wp-content/plugins.
  3. Confirma el memory_limit real usado por el sitio con la comprobación mem.php (Task 9), luego borra ese archivo.
  4. Sube el memory_limit del pool con cautela (256M → 512M) si hace falta (Task 7), recarga FPM (Task 8).

Fase 2: Hacer la memoria predecible (mismo día)

  1. Mide RSS de workers y fija pm.max_children usando la realidad, no la esperanza (Task 16).
  2. Añade reciclaje de workers con pm.max_requests (empieza en 300–1000 según estabilidad del código). Esto limita patrones de crecimiento a largo plazo.
  3. Detén el autoload bloat: mide tamaño (Task 13), lista los culpables (Task 14), cambia autoload a ‘no’ para blobs no críticos (Task 15) y arregla el comportamiento del plugin.
  4. Separa pools para cargas pesadas (admin/media/import) si puedes. Caps diferentes, concurrencia diferente, menos interacciones sorpresa.

Fase 3: Arregla la carga de trabajo (semana 1)

  1. Reproduce en staging con datos similares a producción. La mayoría de problemas de memoria que “solo fallan en prod” son por tamaño de datos.
  2. Reemplaza o parchea el que consume memoria. Los plugins que cargan todo en memoria deben tratarse como riesgo de producción, no como característica.
  3. Haz exports/imports por streaming: lee por chunks, pagina consultas, escribe salida incrementalmente y evita construir arrays gigantes.
  4. Mueve trabajos pesados fuera del path de petición usando cron real y una aproximación de cola/worker. Las peticiones deben ser rápidas; los jobs pueden ser pesados.

Checklist: Dimensionado de pools PHP-FPM que no provoque OOM

  • Mide RSS típico y pico por worker (ps, Task 16).
  • Decide un presupuesto de memoria para workers PHP (p. ej., 40–60% de la RAM tras DB, cache, OS).
  • Calcula pm.max_children ≈ presupuesto / RSS pico (redondea hacia abajo).
  • Configura pm = dynamic con pm.start_servers, pm.min_spare_servers, pm.max_spare_servers sensatos.
  • Establece pm.max_requests para reciclar.
  • Mantén memory_limit lo bastante alto para acciones administrativas legítimas, pero no tan alto que una petición pueda dejar al host sin memoria.

Checklist: Higiene específica de WordPress que previene picos de memoria

  • Mantén las opciones autoload ligeras; alerta cuando el MB de autoload crezca más allá de un umbral.
  • Audita plugins trimestralmente: elimina los abandonados, reemplaza los pesados y suprime solapamientos de funcionalidades.
  • Usa WP-CLI para operaciones bulk controladas con límites de memoria explícitos.
  • Convierte WP-Cron en cron real para que los jobs se ejecuten según horario y no durante peticiones de usuarios.
  • Vigila el uso de admin-ajax; ahí es donde “solo un pequeño informe” se convierte en una petición de 500MB.

FAQ

1) ¿“Allowed memory size exhausted” es un límite de WordPress o de PHP?

Es un límite de PHP. WordPress puede solicitar más memoria mediante constantes, pero PHP aplica el tope real.

2) Puse define('WP_MEMORY_LIMIT','512M'). ¿Por qué sigue fallando?

Porque PHP sigue limitado a un valor inferior (override del pool, php.ini de FPM o memoria de contenedor). Verifica con un endpoint web (Task 9) y arregla el pool correcto (Tasks 5–7).

3) ¿Cuál es un memory_limit sensato para el admin de WordPress?

Para un sitio simple: 256M suele ser suficiente. Para WooCommerce/page builders/administración con analíticas: 512M es común. Por encima de eso, considéralo un olor y busca hinchazón.

4) ¿Debo poner WP_MAX_MEMORY_LIMIT más alto que WP_MEMORY_LIMIT?

Sí. Las peticiones front-end suelen ser más ligeras y previsibles. El admin puede necesitar legítimamente más para actualizaciones, medios, exportaciones y dashboards.

5) ¿Puede OPcache causar errores de agotamiento de memoria?

OPcache no cuenta contra memory_limit de PHP de la misma manera (usa memoria compartida), pero una mala configuración de OPcache puede aumentar latencia y concurrencia, incrementando indirectamente la presión total de memoria de los workers PHP.

6) Si aumento memory_limit, ¿puede empeorar el rendimiento?

Sí, si no ajustas la concurrencia. Topes por worker más grandes con el mismo pm.max_children pueden llevar al host a swapping u OOM. Ajusta el sistema en conjunto.

7) ¿Por qué ocurre solo en ciertas páginas del admin?

Esas páginas activan rutas de código más pesadas: generación de informes, operaciones por lotes, transformaciones de medios o plugins que consultan demasiados datos. Los logs (Task 10) suelen revelar el archivo responsable.

8) ¿Cuál es la forma más rápida y segura de recuperar acceso si wp-admin está muerto?

Desactiva el plugin sospechoso vía WP-CLI (Task 11) o mueve su directorio de plugins. Luego arregla la causa raíz antes de reactivar.

9) ¿Puede la hinchazón de la base de datos causar agotamiento de memoria en PHP?

Indirectamente, sí. Blobs enormes en options (especialmente autoloaded) y consultas sin límite pueden traer grandes conjuntos de resultados a la memoria PHP. Mide el tamaño de autoload (Task 13) y arregla los culpables (Task 14).

10) ¿Cómo evito que esto vuelva a ocurrir tras actualizaciones de plugins?

Usa pruebas en staging con datos reales, monitoriza tendencias de RSS de workers, alerta sobre crecimiento de autoload MB y aplica gobernanza de plugins. La fase de “instalar cualquier cosa” termina cuando pasa a producción.

Conclusión: qué hacer a continuación

Si quieres arreglar esto de forma permanente, deja de tratar el agotamiento de memoria como un único ajuste. Es un comportamiento de sistema.

  1. Hoy: Usa los logs para identificar el endpoint y plugin que fallan, verifica el memory_limit real para web y CLI y estabiliza con un aumento conservador si es necesario.
  2. Esta semana: Mide RSS de workers, fija la concurrencia de PHP-FPM según presupuesto, recicla workers y limpia el autoload bloat.
  3. Continuo: Trata los cambios de plugins como cambios de código—prueba, mide y revierte rápido. Añade alertas para crecimiento de autoload y tasas de errores de memoria.

Haz eso y “Allowed memory size exhausted” volverá a ser lo que debe ser: una valla de seguridad rara, no un evento recurrente en el calendario.

← Anterior
WordPress 403 Forbidden: Diagnosticar y corregir permisos, reglas WAF y bloqueos
Siguiente →
DMARC cuarentena vs rechazo: cuándo cambiar y cómo implementarlo de forma segura

Deja un comentario