El error 504 Gateway Timeout significa que el servidor situado delante de PHP (nginx, una CDN o el proxy del hosting) no recibió respuesta en el tiempo establecido. WordPress normalmente no es el culpable, sino la víctima: la petición espera en cola a que quede libre un worker de PHP o ella misma dura demasiado. Empieza por los logs de PHP-FPM de la hora del fallo y después comprueba si el error afecta a todo el sitio o a una sola dirección.
Qué significa el error 504 en WordPress
MDN, siguiendo el RFC 9110, define el 504 como la situación en la que un servidor que actúa como pasarela o proxy “no recibió a tiempo una respuesta del servidor upstream” (traducción propia). Es distinto del 502 Bad Gateway: allí la respuesta llegó, pero no era válida. En el 504 no llegó nada.
En un hosting WordPress típico la cadena es esta: navegador, opcionalmente una CDN, nginx, PHP-FPM, la base de datos y, en su caso, una caché de objetos. El código 504 lo genera el eslabón que estaba esperando, y eso ya indica dónde buscar. Si nginx espera a PHP, el problema está en PHP, en la base de datos o en la cola de PHP. Si espera la CDN, el problema está en el servidor de origen.
La documentación de MDN advierte además de que las causas son muchas y de que la reparación suele requerir un análisis por parte del administrador del servidor. Por eso aquí no hay una corrección mágica, sino un orden de comprobaciones.
El 504 es culpa del hosting o del sitio
Lo decide el alcance del error. La tabla siguiente es un atajo para decidir, no una sentencia.
| Síntoma | Dirección más probable |
|---|---|
| 504 en todo el sitio, también en subpáginas sencillas | Faltan workers de PHP o el servidor está sobrecargado: hosting o tráfico |
| 504 solo en una dirección | Consulta lenta, plugin o API externa a la que llama esa dirección |
| 504 en wp-admin y al guardar, el front funciona gracias a la caché | Peticiones pesadas de usuarios con sesión iniciada, que se saltan la caché |
| 504 esporádico, siempre en las mismas horas | Tareas programadas, copias de seguridad o picos de tráfico |
| 504 tras cambiar un plugin o actualizar | Conflicto de plugin o migración de base de datos que tarda demasiado |
La responsabilidad del hosting empieza donde los límites (número de workers, memoria, CPU) son demasiado pequeños para el tráfico normal del sitio. La responsabilidad del sitio empieza donde una sola petición hace tanto trabajo que bloquea un worker durante decenas de segundos. En la práctica suelen darse las dos cosas a la vez: las peticiones lentas ocupan a los workers y un pool pequeño no tiene margen.
Por qué mi web de WordPress se cae cada pocas semanas
En noviembre de 2025, en el foro r/webdev, el dueño de dos webs con WordPress, ambas a cargo del mismo desarrollador, preguntó sin rodeos si eso era normal:
Cada pocas semanas, las webs se caen de repente o dejan de funcionar bien: o la página no carga, o algo se rompe. El desarrollador siempre dice que es un problema del hosting o que hay que renovar, hacer una copia o actualizar, y luego ofrece un plan anual de mantenimiento o de copias de seguridad con un coste adicional.
(traducción propia, r/webdev, hilo del 2 de noviembre de 2025)
El hilo reunió decenas de respuestas. Estas son las preguntas que plantea y lo que puedes comprobar por tu cuenta.
Es culpa del hosting o del desarrollador
Las respuestas del hilo se dividieron en dos bandos. Un desarrollador que monitoriza las webs de todos sus clientes escribe que las webs alojadas en hostings más baratos “se caen al menos una vez por semana”, porque no aguantan el tráfico de bots (traducción propia, tomhermans, r/webdev). Otro responde que una web bien configurada en un buen hosting “no debería caerse prácticamente NUNCA” (traducción propia, redlotusaustin, r/webdev).
Las dos cosas pueden ser ciertas a la vez, y la tabla de arriba ayuda a distinguirlas. Si cada caída muestra un 502 o un 504 en toda la web, la culpa suele ser de los recursos: un pool de PHP-FPM demasiado pequeño o un servidor compartido sobrecargado. Si la web falla en un punto y el resto funciona, la causa está en el código, en un plugin o en el tema.
Pueden los bots tumbar una web WordPress en un hosting barato
Sí. Un bot que recorre direcciones sin caché ejecuta PHP en cada petición. En un hosting compartido con pocos workers de PHP, la cola se llena enseguida y las peticiones siguientes terminan con el error 504 que describen las secciones de abajo. Ayudan una caché de páginas delante de PHP (en el servidor o en una CDN) y un límite de peticiones por cliente. Al bloquear bots en Cloudflare, ten cuidado con la opción que también deja fuera a Googlebot, como explicamos en Cloudflare bloquea a Googlebot.
Las actualizaciones de plugins rompen la web de WordPress
Uno de los participantes del hilo señala las actualizaciones de plugins como causa frecuente de caídas cuando se aplican directamente en la web en producción, sin probarlas antes en un entorno de staging (traducción propia, technomalist, r/webdev). Si las caídas coinciden con actualizaciones, compara las fechas de las caídas con el historial de actualizaciones. Cómo trabajar con una copia de pruebas lo explica nuestra guía de staging para WordPress.
Pueden las caídas repetidas significar que han hackeado la web
Sí. En el hilo aparece un ciclo típico: una web infectada a través de un plugin vulnerable se restaura desde una copia de seguridad, pero el agujero sigue abierto, así que a los pocos días todo se repite (traducción propia, 30thnight, r/webdev). Restaurar la copia sin eliminar la causa no acaba con el problema. Los pasos de la limpieza están en la guía para eliminar malware de WordPress.
Cómo saber por qué se ha caído mi web WordPress
La respuesta más corta del hilo dice: “¿Qué dicen tus logs?” (traducción propia, chmod777, r/webdev). Como dueño de la web, puedes hacerlo sin un desarrollador:
- Activa una monitorización externa de disponibilidad que registre la hora y la duración de cada caída.
- Ten tu propio acceso al panel del hosting, no solo al escritorio de WordPress.
- Tras una caída, abre el registro de errores de PHP y el registro de errores del servidor web de esa misma hora. Los errores fatales de PHP apuntan al código o a un plugin; los límites de procesos superados y los timeouts, a los recursos del hosting.
- Compara las horas de las caídas con las fechas de actualización de los plugins, el tema y WordPress.
Vale la pena pagar un plan de mantenimiento de WordPress
Un plan de mantenimiento paga un trabajo regular: actualizaciones probadas antes de publicarlas, monitorización, copias de seguridad y respuesta ante caídas. Pero no debería ser la respuesta a caídas cuya causa nadie ha identificado. Una caída cada pocas semanas no es normal, con plan o sin él. Tras cada caída deberías recibir por escrito la causa y lo que se cambió para que no se repita. Así trabajamos en el mantenimiento de WordPress.
Cómo comprobar dónde se atascó la petición
Empieza por tres sitios, en este orden.
- Log de errores del servidor web de la hora del fallo. En nginx, una entrada
upstream timed outconfirma que el servidor esperaba a PHP. - Log de PHP-FPM. El aviso de que se alcanzó
pm.max_childrensignifica que el pool estaba lleno y las peticiones siguientes esperaban en cola. La opciónpm.max_children, según la documentación de PHP, fija el límite de peticiones simultáneas que atiende el pool. - Log de WordPress. Pon en
wp-config.phpWP_DEBUGentrue,WP_DEBUG_LOGentrueyWP_DEBUG_DISPLAYenfalse. Los errores irán awp-content/debug.logen lugar de a la pantalla. Así lo describe la documentación de WordPress. Desactiva el debug al terminar el diagnóstico.
Si el hosting da acceso al slowlog de PHP-FPM, configura request_slowlog_timeout y PHP guardará el backtrace de las peticiones que duren más que el límite. Por defecto la opción está desactivada (valor 0). El backtrace muestra en qué función del plugin o del tema se quedó esperando PHP.
En un hosting compartido a menudo no hay acceso a estos logs. Entonces, lo primero que hay que pedir al soporte es el acceso a ellos y a las métricas del pool de PHP, junto con la hora del fallo y la dirección que devolvió el 504.
Por qué un pool de PHP-FPM demasiado pequeño provoca un 504
Cada petición dinámica ocupa un worker de PHP-FPM hasta el final de la respuesta. Cuando todos los workers están ocupados, las peticiones nuevas esperan. Si esperan más que el límite del proxy, el visitante ve un 504.
El fastcgi_read_timeout por defecto de nginx es de 60 segundos, y la documentación de nginx aclara que el límite se cuenta entre dos lecturas consecutivas del servidor FastCGI, no para toda la respuesta. En los hostings gestionados el valor puede ser otro, así que no des por hecho que en el tuyo son justo 60 segundos.
Subir pm.max_children solo ayuda si el servidor tiene memoria para ello. Cada worker de WordPress con varios plugins ocupa una parte considerable, de modo que un valor demasiado alto termina agotando la RAM y matando procesos, un estado peor que la cola. La configuración del pool es tarea de un administrador que vea el consumo de memoria.
Cómo provocan un 504 las consultas lentas y las opciones autocargadas
Cuando el 504 afecta a todo el sitio y el pool no está lleno por el tráfico, revisa la base de datos. La documentación de WordPress señala que WordPress repite muchas consultas en cada petición y que las opciones marcadas como autoload se cargan en cada visita. Recomienda mantenerlas por debajo de 800 KB, y las recomendaciones completas están en la guía de optimización. Un plugin que guarda datos grandes en wp_options con autoload los mete en cada petición. El tamaño del autoload se comprueba con una consulta SQL sobre la columna autoload de la tabla de opciones.
Para localizar consultas lentas sirve la constante SAVEQUERIES. Guarda cada consulta, su tiempo de ejecución y la función que la lanzó en $wpdb->queries. Cuesta rendimiento, así que actívala un rato y, si es posible, en staging.
Cuándo provocan un 504 la caché de objetos y Redis
Una caché de objetos persistente reduce el número de consultas a la base de datos y normalmente acelera el sitio. Pero necesita un servidor de caché que funcione y el archivo drop-in wp-content/object-cache.php.
El fallo funciona al revés cuando ese archivo existe y el servidor Redis no responde. Cada petición intenta entonces conectarse a la caché, espera al timeout de conexión y solo después continúa o se rinde. El síntoma es un 504 justo después de un reinicio o de una caída del servicio de caché en el hosting, aunque el código del sitio no haya cambiado.
La prueba es sencilla: cambia el nombre de object-cache.php. Si el 504 desaparece, el culpable es la caché y no WordPress. Restaura el archivo solo después de reparar el servicio.
Cómo provocan un 504 WP-Cron, admin-ajax y las API externas
Conviene revisar por separado tres fuentes de peticiones lentas aisladas.
- WP-Cron. La documentación de WordPress explica que WP-Cron se ejecuta cuando alguien entra en el sitio, no como un proceso permanente. Las tareas pesadas y atrasadas (copias de seguridad, importaciones, envíos) pueden, por tanto, cargar la petición normal de un visitante. Trasladar las llamadas al cron del sistema del hosting descarga el front.
- admin-ajax.php. Los plugins envían aquí peticiones desde el panel y desde el front. Si el 504 aparece justo aquí, busca el plugin que hace una operación pesada en segundo plano.
- API externas. Un plugin que espera a un sistema externo lento (pagos, ERP, envíos) retiene al worker mientras el otro sistema tarda en responder. Si ese plugin no tiene un timeout propio y corto, la caída ajena se convierte en tu 504.
En qué se diferencia el 504 del 502 y del 524
- 502 Bad Gateway: el servidor situado detrás del proxy respondió, pero la respuesta no era válida. A menudo es un proceso de PHP-FPM caído.
- 504 Gateway Timeout: ausencia de respuesta a tiempo. Lo más frecuente es una sobrecarga o una petición lenta.
- 524: código de Cloudflare. La documentación de Cloudflare indica que aparece cuando el servidor de origen no responde en los 125 segundos por defecto. Cloudflare aconseja pedir al hosting que revise los procesos largos y la sobrecarga, y mover las operaciones grandes a un canal sin proxy.
Detrás de una CDN puedes, por tanto, ver dos códigos distintos para la misma causa, según qué eslabón perdió antes la paciencia.
Cuándo subir el timeout y cuándo no
Subir fastcgi_read_timeout o el límite de tiempo de PHP está justificado para una operación aislada y deliberadamente larga, por ejemplo una importación manual. Para un sitio que muestra 504 a los visitantes es enmascarar el problema: la petición lenta sigue ocupando un worker, solo que durante más tiempo, y el pool se llena más rápido.
PHP-FPM tiene otro fusible, request_terminate_timeout. La documentación lo describe como el límite tras el cual se mata el proceso que atiende la petición, y da como valor por defecto 0, es decir, desactivado. Bien ajustado, protege al pool de un único script colgado.
Actualización del . Las tareas largas de wp-admin, como una copia de seguridad o una exportación de la base de datos, son una causa clásica de 504 en hosting compartido. En ese tipo de plan casi nunca puedes cambiar el límite del proxy, y el proxy corta la petición antes de que PHP termine, diga lo que diga max_execution_time. La solución es dividir la tarea en peticiones cortas que puedan reanudarse. Nuestro plugin Migrator muestra el patrón. Desde la versión 1.6.0, una copia de seguridad lanzada desde wp-admin exporta la base de datos por pasos, un bloque de filas por petición, así que una base de datos grande se exporta sin un 504 Gateway Timeout en hosting compartido. Un paso interrumpido se reanuda donde se detuvo el anterior, y el filtro migrator_step_seconds fija cuánto tiempo puede trabajar cada paso, para servidores cuyo proxy corta antes las peticiones. Si la exportación o importación de un plugin muere con un 504 siempre en un punto parecido, busca un modo que trabaje por bloques y pueda reanudarse, o comandos de WP-CLI (Migrator tiene comandos wp migrator desde la versión 1.5.0). Subir los límites de PHP no sirve, porque el proxy los ignora.
Qué timeouts de nginx terminan en un error 504
El módulo FastCGI de nginx tiene tres temporizadores distintos y, según la documentación de ngx_http_fastcgi_module, cada uno vale 60 segundos por defecto.
| Directiva | Qué mide | Por defecto |
|---|---|---|
fastcgi_connect_timeout | el establecimiento de la conexión con PHP-FPM | 60 s, normalmente no más de 75 s |
fastcgi_send_timeout | la pausa entre dos escrituras consecutivas de la petición hacia PHP-FPM | 60 s |
fastcgi_read_timeout | la pausa entre dos lecturas consecutivas de la respuesta | 60 s |
Los dos últimos temporizadores se reinician con cada bloque de datos. Un script que envía algo de vez en cuando puede, por tanto, trabajar más de un minuto sin error. Un script que se queda en silencio porque espera a la base de datos o a una API externa recibe un 504 a los 60 segundos. fastcgi_send_timeout importa sobre todo en peticiones POST grandes, como la subida de un archivo o una importación.
Cuando nginx está delante de Apache y no directamente delante de PHP-FPM, el que cuenta es proxy_read_timeout del módulo ngx_http_proxy_module. También vale 60 segundos y también mide la pausa entre lecturas, no la respuesta completa.
Todas estas directivas son válidas en los contextos http, server y location. Por eso puedes subir el límite solo para la ruta que de verdad lo necesita, en lugar de hacerlo para todo el servidor:
location = /wp-admin/admin-ajax.php {
# límite mayor solo aquí, el resto del servidor sigue en 60 s
fastcgi_read_timeout 120s;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php-fpm.sock;
}La ruta del socket de PHP-FPM cambia entre distribuciones y hostings, así que cópiala de tu configuración actual y no del ejemplo.
Timeout de Apache con PHP-FPM y mod_proxy_fcgi
Apache pasa PHP a PHP-FPM mediante mod_proxy_fcgi, normalmente con SetHandler "proxy:unix:/ruta/al/socket.sock|fcgi://localhost/". Aquí el tiempo de espera depende de tres ajustes, y cada uno toma su valor por defecto del siguiente:
Timeout, del núcleo de Apache, 60 segundos por defecto. La documentación de Apache indica que enmod_proxyes el valor por defecto cuando no se ha definidoProxyTimeout.ProxyTimeout, de mod_proxy, igual aTimeoutpor defecto. La documentación lo describe como una forma de devolver un timeout cuando un servidor de aplicaciones se queda colgado, en lugar de esperar lo que haga falta.- el parámetro
timeoutenProxyPasso en la definición de un worker, igual aProxyTimeoutpor defecto. Es el número de segundos que Apache espera datos enviados al backend o recibidos de él.
Los tres tienen el contexto server config y virtual host, así que no funcionan en .htaccess. En un hosting compartido solo puede cambiarlos el administrador del servidor.
Por qué max_execution_time no evita el 504
max_execution_time en PHP vale 30 segundos por defecto, menos que los 60 segundos de nginx. Parece entonces que PHP siempre cortará el script antes de que el proxy devuelva un 504. No es así. La documentación de PHP señala que, en sistemas que no son Windows, las llamadas al sistema y las operaciones con streams no cuentan para ese límite, y la página de set_time_limit() añade que el tiempo dedicado a consultas a la base de datos tampoco se cuenta.
En la práctica, una petición de WordPress que espera 70 segundos a una tabla MySQL bloqueada o a una pasarela de pago nunca alcanza el límite de PHP. El worker sigue ocupado y nginx devuelve un 504 tras 60 segundos de silencio. La excepción son las compilaciones de PHP con --enable-zend-max-execution-timers (la opción por defecto en las compilaciones ZTS desde PHP 8.3.0), donde el límite mide el tiempo transcurrido, incluida la espera de entrada y salida.
Por eso, con API externas, lo que cuenta es el timeout de la propia conexión. Las funciones HTTP de WordPress (WP_Http::request) tienen un timeout por defecto de 5 segundos, ajustable con el filtro http_request_timeout. Un plugin que lo sube a un minuto quita esa protección, y es ese plugin el que convierte una API lenta en un 504.
De estas cifras sale un orden que facilita el diagnóstico: cada límite interior más corto que el exterior. El timeout HTTP del plugin (5 s) por debajo del límite de PHP (30 s), este por debajo de fastcgi_read_timeout (60 s) y este por debajo de los 125 segundos de Cloudflare. Cuando salta primero el límite interior, el error queda en debug.log con el nombre de la función que estaba esperando. Cuando salta primero el exterior, solo queda una página 504 genérica sin rastro en los logs de WordPress.
Cómo leer la página de estado de PHP-FPM
La prueba más rápida de si un 504 viene de una cola o de una sola petición lenta es la página de estado de PHP-FPM. Se activa con la opción pm.status_path en la configuración del pool, que por defecto no está definida. La documentación de PHP advierte de que la página muestra las URL de las peticiones e información sobre los recursos, así que conviene restringirla a peticiones internas o a direcciones IP conocidas. El parámetro ?json devuelve JSON y ?full añade el detalle de cada proceso.
| Campo | Qué significa |
|---|---|
listen queue | peticiones que ahora mismo esperan un proceso libre |
max listen queue | la cola más larga desde el arranque del pool |
active processes / idle processes | procesos ocupados y libres |
max children reached | 1 o más si el pool ha llegado alguna vez a pm.max_children |
slow requests | peticiones que superaron request_slowlog_timeout |
Durante una caída, la lectura es sencilla. Una cola mayor que cero y ningún proceso libre significan un pool lleno: faltan workers o hay peticiones lentas que los retienen. Una cola vacía y procesos libres al mismo tiempo que un 504 significan que el tiempo se pierde dentro de la propia petición, es decir, en la base de datos, la caché o una API externa. El tope de la cola lo fija listen.backlog, 511 por defecto en Linux según la referencia de configuración de FPM.
Cómo arreglar un 504 paso a paso
- Determina el alcance: todo el sitio, una sola dirección o solo wp-admin.
- Lee los logs del servidor y de PHP-FPM de la hora del fallo.
- Activa
debug.logy reproduce el error. - Desactiva los plugins (con WP-CLI o renombrando el directorio), después ve activándolos de uno en uno y mide el tiempo de respuesta.
- Si existe
object-cache.php, desactívalo como prueba. - Revisa las opciones autocargadas y las tareas atrasadas de WP-Cron.
- Solo al final, plantéate aumentar el pool o los timeouts, junto con el administrador del hosting.
Si el 504 apareció justo después de una actualización, consulta también la guía sobre cómo recuperar WordPress tras una actualización fallida.
Cuándo es trabajo para un especialista
Cuando los logs apuntan al pool de PHP-FPM, pero el hosting no da acceso a su configuración. Cuando el 504 vuelve tras cada reparación. Cuando la tienda pierde pedidos durante la caída. En una auditoría que deba separar el coste del hosting del coste del código, ayuda la optimización de la velocidad de WordPress. Si el sitio está caído ahora y se desconoce la causa, la salida es el servicio de reparación y soporte técnico de WordPress.






