Error 504 Gateway Timeout: encontrar qué lo ralentiza
· 6 min de lectura
Qué significa el error
Con un 504, el servidor web de delante (nginx, Apache, un balanceador de carga, un CDN) se da por vencido con la aplicación de detrás: la petición se transmitió y el backend seguía trabajando cuando el contador de delante llegó a cero. La diferencia con el 502 Bad Gateway: el backend es alcanzable, solo es demasiado lento. Tiempos de espera habituales: 60 segundos en nginx (fastcgi_read_timeout, proxy_read_timeout) y en Apache (ProxyTimeout), 100 segundos en Cloudflare.
Subir el tiempo de espera rara vez es la solución. Algo tarda demasiado, y eso hay que encontrarlo.
Causas frecuentes
- Una consulta SQL lenta. Un plugin que cuenta las filas de una tabla enorme en cada página, un índice que falta, una tabla
wp_optionsllena de transients expirados. Bajo carga, las esperas se suman. - Una llamada externa que se queda colgada. La aplicación consulta a un proveedor de pagos o a un servicio de correo, y ese servicio está lento o caído. Sin un tiempo de espera propio, tu página espera con él.
- Muy pocos workers. Todos los workers de PHP-FPM están atrapados en peticiones lentas; las nuevas hacen cola hasta que el servidor de delante se rinde. Visto desde fuera, es un timeout.
- Cron o copia de seguridad en primer plano. Una copia de seguridad, una importación, un sitemap enorme: generados dentro de una petición web, superan cualquier tiempo de espera.
- Swap. Al servidor le falta memoria, usa el swap y todo se vuelve diez veces más lento: carga alta, procesador poco ocupado.
- Red entre el servidor de delante y el backend. Raro, pero un 504 en cada petición con un backend sin actividad apunta ahí.
Si eres visitante
Recarga en un minuto. Si el sitio está lento en lugar de caído, prueba otra página; quizá la culpa sea de una sola página pesada.
Si el sitio es tuyo: comprobar primero
Abre el Website down checker: muestra el código HTTP y el tiempo de respuesta vistos desde fuera. Un sitio que hoy tarda 30 segundos mañana da un 504.
En tu propio servidor, el tiempo perdido se busca aquí:
# ¿hay timeouts en los logs?
sudo tail -n 30 /var/log/nginx/error.log | grep -E 'timed out|timeout'
# ¿qué está haciendo PHP? (requiere pm.status_path en el pool)
curl -s 'http://127.0.0.1/fpm-status?full' | grep -E 'state|request URI|duration' | head -40
# MySQL/MariaDB: ¿qué consultas se ejecutan y desde cuándo?
sudo mysql -e 'SHOW FULL PROCESSLIST;'
# memoria y swap
free -m
vmstat 1 5
Una lista llena de la misma consulta o columnas si/so distintas de cero nombran la causa.
Soluciones en tu propio servidor
1. Activar el log de consultas lentas y corregir la consulta
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
Tras unos minutos, sudo mysqldumpslow -s t /var/log/mysql/slow.log | head enumera las peores consultas. Crea el índice que falta o sustituye el plugin que lanza la consulta. En WordPress, la tabla de opciones que crece sin parar es un clásico: wp transient delete --all suele ayudar.
2. Dar un tiempo de espera a las llamadas externas
Cada llamada HTTP de tu aplicación necesita su propio tiempo de espera, más corto que el del servidor web. En PHP con cURL: CURLOPT_CONNECTTIMEOUT en 5 y CURLOPT_TIMEOUT en 10. En WordPress, wp_remote_get() acepta un argumento timeout. Si un servicio de terceros está caído, la página debe salir en versión reducida, no morir.
3. Sacar los procesos largos de la petición
Copias de seguridad, importaciones, exportaciones, sitemaps y envíos de correo van a una tarea cron o a una cola, no a una página. En WordPress, desactiva el pseudocron e instala el de verdad:
// wp-config.php
define('DISABLE_WP_CRON', true);
# crontab -e
*/5 * * * * cd /var/www/example.com && wp cron event run --due-now >/dev/null 2>&1
4. Ajustar los tiempos de espera, con medida
Si una página necesita de verdad más tiempo (una exportación, un informe), sube el tiempo de espera solo para ella, no de forma global:
location = /wp-admin/export.php {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_read_timeout 300;
}
Apache: ProxyTimeout 300 dentro de un bloque <Location>. Pon max_execution_time de PHP en el mismo valor; si no, PHP se rinde primero con un 500. Después, sudo nginx -t && sudo systemctl reload nginx.
5. Dejar de usar el swap
ps aux --sort=-%mem | head
Si cada worker de PHP-FPM ocupa 150 MB y lanzas 30 en un servidor de 4 GB, las cuentas no salen. Baja pm.max_children, pon más memoria o arregla el plugin que la devora.
6. Poner caché
Una caché de páginas (la caché FastCGI de nginx, un plugin de WordPress, Varnish) atiende a los visitantes sin tocar PHP ni la base de datos. La mayoría de los 504 bajo carga desaparecen en cuanto las páginas más visitadas salen de ella.
Si el problema está en tu proveedor de hosting
En un hosting compartido puedes corregir consultas lentas y plugins, pero no los tiempos de espera del servidor ni la carga de los vecinos:
Hola, mi sitio example.com devuelve « 504 Gateway Timeout » desde aproximadamente las 16:00 (UTC). Páginas que hasta ahora eran rápidas superan ahora el tiempo de espera. No he modificado nada. ¿Pueden comprobar si el servidor de base de datos o el pool de PHP de mi cuenta está sobrecargado, o si otra cuenta está generando mucha carga?
Para que no vuelva a pasar
Un 504 es un sitio lento que se volvió aún más lento, y el tiempo de respuesta se mide mucho antes del timeout. Las comprobaciones del sitio lo registran en cada pasada; ponle una alerta y verás la tendencia mucho antes de que los visitantes vean un error. El monitoring de servidores suma carga, memoria y swap desde dentro.
¿Caído? Intervenimos. En tu propio servidor o en un hosting compartido con acceso SSH, la intervención a fondo encuentra la consulta lenta o la llamada colgada y la corrige, las 24 horas, todos los días, en bloques de 15 minutos, precio visible antes de pedir; la intervención rápida, a precio fijo, reinicia un servicio detenido.
Y ahora
Comprobar desde fuera
¿El sitio está caído para todo el mundo o solo para ti, y qué responde el servidor? Gratis, sin registro.
Website down checker¿Caído? Intervenimos.
En tu propio servidor o en un hosting compartido con acceso SSH: intervención rápida a precio fijo para las causas frecuentes, intervención a fondo facturada en bloques de 15 minutos para todo lo demás, 24/7. Precio visible antes de pedir.
Solicitar una reparaciónOtras guías
- Sitio web caído: qué hacer en los primeros 15 minutos
- Servidor caído: qué revisar primero y en qué orden
- Error 500 Internal Server Error: encontrar la causa en los logs y recuperar el sitio
- Error 502 Bad Gateway: encontrar la causa y solucionarlo
- Error 503: ¿sobrecarga, mantenimiento o límite del hosting?
- Error 521 y 522 de Cloudflare: el servidor de origen no responde
- DNS_PROBE_FINISHED_NXDOMAIN: el dominio ya no responde
- ERR_CONNECTION_REFUSED: el servidor rechaza la conexión
- ERR_CONNECTION_TIMED_OUT: el servidor no responde a tiempo
- Qué significa «La conexión no es privada» y cómo solucionarlo
- ERR_SSL_PROTOCOL_ERROR: la conexión segura falla antes del certificado