// Engineering Log

HTTPS y servidor web en la práctica: Parte 1 — Errores 502, 504, 499 y 413 en Nginx: causas y tiempos de espera

Publicado el 28.10.2026

// Ruta rapida

Este articulo pertenece al tema Servidores e infraestructura.

Los códigos 502, 504, 499 y 413 casi nunca los devuelve la propia aplicación. Los devuelve Nginx, que está delante de ella: no pudo conectarse a la aplicación, no esperó la respuesta, hubo un corte de conexión o rechazó aceptar una petición demasiado grande. Por eso la causa se busca no en el código de la aplicación, sino en la intersección entre Nginx y la aplicación — en el registro de errores de Nginx y en la conciliación de timeouts. Más abajo — qué significa cada código, qué líneas del registro le corresponden y qué cambiar en la configuración. Información general sobre códigos de estado — en el artículo HTTP, HTTPS y TLS: Parte 1 — Qué es HTTP: solicitud, respuesta, métodos y códigos de estado.

Primero — el registro

En access.log solo se ve el código; la causa está en error.log (habitualmente /var/log/nginx/error.log). La línea de error contiene la dirección de la aplicación (upstream), la petición y la razón del sistema:

2026/09/24 10:15:02 [error] 1234#1234: *5678 connect() failed (111: Connection refused)
while connecting to upstream, client: 192.0.2.7, server: example.ru,
request: "GET /api/orders HTTP/2.0", upstream: "http://127.0.0.1:8080/api/orders"

Para ver el tiempo de respuesta de la aplicación directamente en el log de acceso, amplíe el formato:

nginx
log_format upstream '$remote_addr "$request" $status '
                    'rt=$request_time uct=$upstream_connect_time '
                    'urt=$upstream_response_time us=$upstream_status ua=$upstream_addr';
access_log /var/log/nginx/access.log upstream;
  • $request_time — cuánto tiempo Nginx procesó la petición en total, incluyendo la transferencia al cliente;
  • $upstream_connect_time — tiempo de conexión a la aplicación;
  • $upstream_response_time — cuánto respondió la aplicación;
  • $upstream_status y $upstream_addr — qué devolvió la aplicación y cuál de los servidores. Si hay varios servidores y Nginx probó el siguiente, los valores van separados por comas: 502, 200.

502 Bad Gateway

Nginx no recibió de la aplicación una respuesta correcta. La causa la determina el texto en error.log.

connect() failed (111: Connection refused) — en la dirección y puerto indicados no hay nadie escuchando. La aplicación no está arrancada, se cayó, escucha otro puerto o solo 127.0.0.1 cuando Nginx se conecta por la dirección externa (caso frecuente en Docker: la aplicación escucha 127.0.0.1 dentro del contenedor y no es accesible desde otro). Verificación:

bash
ss -ltnp | grep 8080
curl -v http://127.0.0.1:8080/

connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) — no existe el socket: PHP-FPM no está arrancado o en Nginx se indicó otra versión de PHP.

(13: Permission denied) while connecting to upstream — Nginx no tiene permisos sobre el socket (verifique listen.owner y listen.group en el pool de PHP-FPM) o, en CentOS, Rocky y RHEL, SELinux prohíbe la conexión: setsebool -P httpd_can_network_connect 1.

(11: Resource temporarily unavailable) while connecting to upstream — la cola de conexiones al socket está llena: todos los procesos PHP-FPM están ocupados. Busque en el registro de PHP-FPM el mensaje server reached pm.max_children setting y aumente pm.max_children si la memoria lo permite, o busque peticiones lentas.

upstream prematurely closed connection while reading response header from upstream — la aplicación cerró la conexión sin responder. Causas: el proceso se cayó en esa petición (consulte el registro de la aplicación, dmesg por si actúa el OOM killer), la aplicación cortó una petición larga por su propio timeout, o una condición de carrera con keepalive (abajo).

recv() failed (104: Connection reset by peer) — la aplicación reinició la conexión. Las causas son las mismas.

upstream sent too big header while reading response header from upstream — las cabeceras de la respuesta no caben en el buffer: normalmente cookies numerosas o muy grandes, o un Location largo. Aumente el buffer:

nginx
proxy_buffer_size 16k;
proxy_buffers 8 16k;
# para PHP-FPM — fastcgi_buffer_size y fastcgi_buffers

no live upstreams while connecting to upstream — todos los servidores en el bloque upstream están marcados como no disponibles tras errores (parámetros max_fails y fail_timeout). Esto es consecuencia: busque en el registro los primeros errores antes de esta línea.

Condición de carrera keepalive: 502 cada pocos minutos

Si los 502 aparecen de forma poco frecuente, sin carga y sin errores en el registro de la aplicación, casi seguro es una condición de carrera de keepalive entre Nginx y la aplicación.

Cuando en upstream está activado keepalive, Nginx mantiene conexiones abiertas hacia la aplicación y las reutiliza. La aplicación también cierra las conexiones inactivas — pero según su propio timeout. Si la aplicación cerró la conexión en el momento en que Nginx envió por esa conexión una nueva petición, la petición sufre un corte y se obtiene un 502.

Ejemplo: en Node.js server.keepAliveTimeout por defecto es 5 segundos, mientras que Nginx mantiene la conexión inactiva hacia la aplicación hasta 60 segundos (keepalive_timeout en el bloque upstream). Tras 5 segundos de inactividad Node.js cierra la conexión, Nginx intenta reutilizarla — y recibe 502.

Regla: el timeout de inactividad de quien está más cerca de la aplicación debe ser mayor que el de quien está delante de él. O reduzca el timeout en Nginx, o aumente el de la aplicación:

nginx
upstream app {
    server 127.0.0.1:3000;
    keepalive 32;
    keepalive_timeout 4s;    # menor que keepAliveTimeout en Node.js (5 s)
}

server {
    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;
        proxy_set_header Connection "";   # sin esto, keepalive hacia la aplicación no funciona
    }
}
javascript
// o en Node.js: mayor que el timeout de quien está delante de la aplicación
server.keepAliveTimeout = 65000;
server.headersTimeout = 66000;

La misma regla aplica a toda la cadena: balanceador en la nube → Nginx → aplicación. En AWS ALB el timeout de inactividad por defecto es 60 segundos, por tanto el keepalive_timeout de Nginx hacia los clientes debe ser mayor a 60 segundos.

504 Gateway Timeout

Nginx se conectó a la aplicación, pero no esperó la respuesta dentro del tiempo asignado:

upstream timed out (110: Connection timed out) while reading response header from upstream

Timeouts de Nginx al proxy:

DirectivaPor defectoQué limita
proxy_connect_timeout60 sel establecimiento de la conexión con la aplicación (no se puede poner > 75 s)
proxy_send_timeout60 sla pausa entre dos operaciones de escritura de la petición hacia la aplicación
proxy_read_timeout60 sla pausa entre dos operaciones de lectura de la respuesta — no el tiempo total de respuesta
fastcgi_read_timeout60 slo mismo para PHP-FPM

Qué hacer:

  1. Encontrar la petición lenta. 504 es un síntoma: la aplicación tarda demasiado. Mire urt= en el log, consultas lentas a la base de datos, APIs externas sin timeouts.

  2. Aumentar el timeout solo donde la respuesta larga sea normal, por ejemplo para volcado de informes, y no de forma global:

    nginx
    location /reports/ {
        proxy_pass http://app;
        proxy_read_timeout 300s;
    }
  3. Conciliar los timeouts en toda la cadena. Aumentar proxy_read_timeout es inútil si antes salta el timeout en otro punto: max_execution_time y request_terminate_timeout en PHP, timeout del worker en Gunicorn (--timeout, por defecto 30 s), timeout del CDN (en Cloudflare la respuesta debe comenzar en 100 segundos, si no — error 524).

  4. Operaciones largas — en background. Si un informe tarda cinco minutos en generarse, lo correcto es aceptar la tarea, devolver 202 Accepted y entregar el resultado cuando esté listo, en lugar de mantener el HTTP abierto.

proxy_connect_timeout se dispara solo si la aplicación no responde al intento de conexión en absoluto (dirección inaccesible, paquetes perdidos) — en ese caso en el log aparece while connecting to upstream. Un rechazo de conexión (Connection refused) llega al instante y produce 502, no 504.

499 Client Closed Request

Código inventado por Nginx: el cliente cerró la conexión sin esperar la respuesta. Ese código no se envía al cliente — solo se registra.

Causas:

  • el usuario cerró la pestaña o se fue de la página mientras cargaba. 499 aislados son normales;
  • el cliente tiene su propio timeout menor que el tiempo de respuesta: la app móvil espera 30 s y la API responde en 40. 499 masivos con el mismo $request_time son indicio de esto;
  • delante de Nginx hay un balanceador o CDN con su propio timeout que cierra la conexión antes;
  • un sistema de monitorización comprueba disponibilidad con un timeout corto.

Por defecto, cuando el cliente se va, Nginx cierra también la conexión con la aplicación (proxy_ignore_client_abort off), pero la aplicación puede continuar trabajando sin saber que el resultado ya no interesa. Si los 499 son masivos — es el mismo problema que 504: respuestas lentas, solo que el timeout se disparó en el cliente.

413 Content Too Large

El cuerpo de la petición es mayor que lo permitido. En Nginx por defecto es 1 MB, por eso la subida de una foto o documento a través del sitio choca primero con este límite:

client intended to send too large body: 5242880 bytes
nginx
server {
    client_max_body_size 50m;   # para todo el sitio
    location /upload/ {
        client_max_body_size 500m;   # para subidas — mayor
    }
}

El límite existe también más adelante en la cadena, y hay que aumentarlo en todos los sitios:

  • PHP — upload_max_filesize y post_max_size en php.ini;
  • framework de la aplicación — por ejemplo, DATA_UPLOAD_MAX_MEMORY_SIZE en Django, bodyParser en Express;
  • CDN — en Cloudflare en los planes gratuito y Pro el cuerpo de la petición está limitado a 100 MB.

Para archivos grandes es mejor la subida por partes (protocolo tus) o subir directamente al almacenamiento de objetos mediante un enlace firmado, evitando pasar por la aplicación.

Otros códigos de Nginx

  • 400 Request Header Or Cookie Too Large — las cabeceras o cookies no caben en el buffer: large_client_header_buffers 4 16k;.
  • 503 Service Temporarily Unavailable — a menudo no es una avería, sino una limitación por rate limiting (limit_req o limit_conn): por defecto responden con 503. En el registro aparece limiting requests, excess:. Puede devolver el código correcto 429 con la directiva limit_req_status 429;.
  • 500 con rewrite or internal redirection cycle — ciclo infinito en try_files o rewrite.
  • 403 con directory index of "/var/www/…/" is forbidden — se solicitó un directorio, no tiene index.html/index.php y el listado está desactivado. Con (13: Permission denied) — el usuario de Nginx no tiene permisos sobre los archivos.

Errores de Cloudflare 52x

Si el sitio está detrás de Cloudflare, los errores en la intersección entre el CDN y su servidor tienen sus propios códigos — son análogos a 502 y 504, pero entre Cloudflare y Nginx:

CódigoQué significa
520el servidor devolvió una respuesta vacía o inválida
521el servidor rechazó la conexión — Nginx no está en ejecución o el puerto está cerrado para las direcciones de Cloudflare
522timeout al conectar con el servidor
523servidor inaccesible (dirección DNS incorrecta)
524la conexión existe, pero la respuesta no comenzó en 100 segundos
525no se pudo completar el handshake TLS con el servidor
526certificado inválido en el servidor en modo Full (strict)

Orden de diagnóstico

  1. Encontrar la línea en error.log por tiempo y dirección — el texto de error casi siempre indica la causa.
  2. Probar la aplicación directamente, saltándose Nginx: curl -v http://127.0.0.1:8080/ruta.
  3. Comparar $request_time y $upstream_response_time: si el tiempo se consume en la aplicación — buscar allí; si no — en la red o en Nginx.
  4. Anotar los timeouts de toda la cadena — CDN, balanceador, Nginx, aplicación, base — y comprobar que cada uno está conciliado con el anterior.
  5. Para 502 raros sin causa aparente — revisar el keepalive entre Nginx y la aplicación.

// Tarea parecida

Si estas resolviendo algo parecido

Este articulo pertenece a uno de los temas principales de trabajo. Puedes seguir leyendo sobre el tema, ir a la pagina principal para entender a que me dedico o abrir directamente los servicios.

Tema del articulo

Servidores e infraestructura

VPS, Linux, stack web, migraciones, hosting, bases de datos y operacion base.

Tareas frecuentes de esta tema

  • Migrar un sitio o servicio a un nuevo servidor
  • Configurar Linux, Nginx, base de datos y copias de seguridad
  • Entender por que el sistema funciona de forma inestable

// Siguiente paso

Si necesitas ayuda con este tema y no solo otro articulo, es mejor ir directo a la pagina del servicio. La pagina principal y la seleccion de materiales quedan como rutas secundarias.

Abrir servicios

// Reviews

Reseñas relacionadas

apande

apande

Configuración de Nginx y OpenCart

07.09.2024 · ★ 5/5

Un comprador muy poderoso
kireevk

kireevk

Diagnóstico de Nginx Proxy Manager en un contenedor Docker y solución del problema

15.03.2024 · ★ 5/5

Comprador acostumbrado

// Contact

¿Necesitas ayuda?

Escríbeme y te ayudaré a resolver el problema

Respondo en un día laborable (03:00-13:00 GMT)

Или оставьте заявку здесь:

Confirme que no es un bot.

Escribir y recibir una respuesta rápida