Un errore 504 Gateway Timeout significa che un server che fa da gateway o da proxy ha atteso una risposta dal server dietro di sé e ha rinunciato. La richiesta è arrivata alla tua CDN, al load balancer o al web server, è stata inoltrata all’applicazione e l’applicazione non ha risposto prima dello scadere del tempo limite.
Spesso il server dietro il proxy è ancora in funzione. È solo troppo lento, oppure lo è qualcosa che sta aspettando. Per questo un 504 è diverso dalla maggior parte delle interruzioni: riavviare i servizi raramente lo risolve a lungo. Questa guida mostra come capire quale timeout è scattato, cosa rende di solito lenta la richiesta e come risolvere la causa anziché il sintomo.
Cosa ti dice un 504
Una richiesta a un sito moderno attraversa diversi livelli, e ognuno ha il proprio limite di attesa per il successivo:
Una CDN come Cloudflare attende la tua origine per un tempo fisso.
Un load balancer ha un timeout di inattività o di risposta per ogni target.
nginx attende l’upstream secondo proxy_read_timeout o fastcgi_read_timeout, 60 secondi di default.
L’applicazione ha i propri limiti, come max_execution_time di PHP o il timeout dei worker in Gunicorn.
Il 504 arriva dal primo livello il cui limite scade. I suoi vicini significano altro: un 502 Bad Gateway indica che l’upstream ha risposto con qualcosa di non valido o non ha risposto affatto, mentre un 503 Service Unavailable indica che il servizio ha rifiutato la richiesta perché sovraccarico o in manutenzione.
Trova il timeout che è scattato
Cronometra la richiesta. Un 504 che arriva sempre dopo lo stesso numero di secondi punta a un limite preciso:
curl -s -o /dev/null -w “status %{http_code} after %{time_total}s\n” https://www.example.com/reports
status 504 after 60.04s
Poi guarda gli header della risposta e la pagina di errore per capire quale livello ha risposto, come per qualsiasi errore 5xx. Una semplice pagina di nginx con server: nginx significa che è andato in timeout il tuo web server. Una pagina con il marchio della CDN che nomina il tuo host significa che è andata in timeout la CDN mentre aspettava la tua origine.
nginx registra il timeout insieme all’indirizzo che stava aspettando:
upstream timed out (110: Connection timed out) while reading response header from upstream,
upstream: “fastcgi://unix:/run/php/php8.3-fpm.sock”, request: “GET /reports HTTP/2.0”
Ora sai quale pagina è lenta e quale parte dello stack l’ha fatta aspettare. Il passo successivo è capire perché.
Cause comuni e come risolverle
Query al database lente
È la causa più comune. Una query che con mille righe impiegava 50 millisecondi ne impiega 40 secondi con un milione, perché scansiona l’intera tabella. Attiva lo slow query log e cerca le query della pagina:
# MySQL / MariaDB
SET GLOBAL slow_query_log = ‘ON’;
SET GLOBAL long_query_time = 1;
# PostgreSQL, in postgresql.conf
log_min_duration_statement = 1000
Esegui la query più lenta con EXPLAIN e cerca le scansioni complete delle tabelle. Di solito la soluzione è un indice mancante. L’altro sospettato abituale sono i lock: una transazione lunga o una migrazione può bloccare una tabella mentre ogni richiesta che ne ha bisogno resta in attesa.
API esterne lente
Spesso le pagine chiamano altri servizi mentre vengono generate: un provider di pagamento, un calcolatore delle spedizioni, un motore di ricerca, un CRM. Se quel servizio è lento, la tua pagina è lenta e il proxy va in timeout. Imposta un timeout breve su ogni chiamata in uscita, pochi secondi anziché il default della libreria, e decidi cosa mostra la pagina quando la chiamata fallisce. Una stima di spedizione che dice “calcolata al checkout” è meglio di un 504.
Tieni d’occhio i servizi da cui dipendi. Il monitoraggio dei servizi di terze parti di Uptimecheck segue le pagine di stato di 31 servizi come Klarna, Shopify e Cloudflare, così un provider lento compare accanto ai tuoi controlli.
Troppo pochi worker per il traffico
Quando tutti i worker sono occupati, le nuove richieste aspettano in coda. Non sono lente di per sé, stanno aspettando il loro turno, e intanto l’orologio del proxy continua a correre. PHP-FPM lo segnala nel suo log con server reached pm.max_children. Più worker aiutano solo se il server ha memoria e CPU sufficienti. Spesso la soluzione migliore è rendere ogni richiesta più breve, così gli stessi worker ne servono di più, e mettere in cache le pagine che non cambiano da un visitatore all’altro.
Job lunghi dentro una richiesta web
Esportazioni, importazioni, generazione di report, elaborazione di immagini e invio di centinaia di email non appartengono a una richiesta web. Durano quanto durano, e prima o poi uno di questi supera un timeout. Spostali in una coda in background: la richiesta avvia il job e risponde subito, poi la pagina controlla periodicamente il risultato oppure l’utente riceve un’email quando è pronto.
Il server stesso è sovraccarico
CPU alta, poca memoria che spinge il server in swap o un disco che non tiene il passo rallentano tutto contemporaneamente. Un 504 su ogni pagina, non solo su una, porta qui. Controlla CPU, memoria, swap e attesa del disco nello stesso intervallo:
uptime
free -m
iostat -x 5 3
Il monitoraggio dei server conserva questo storico, così puoi vedere cosa stava facendo il server nel minuto in cui sono iniziati i 504 invece di tirare a indovinare dopo.
Problemi di rete tra i livelli
Se il proxy non riesce proprio a raggiungere l’upstream, per esempio perché un firewall scarta i pacchetti invece di rifiutarli, la connessione resta appesa finché non va in timeout. Il risultato è un 504 e non un 502. Verifica che il proxy riesca ad aprire una connessione all’indirizzo e alla porta dell’upstream dalla stessa macchina.
Quando ha senso alzare il timeout
A volte una richiesta è legittimamente lunga: un upload di grandi dimensioni, un report che un amministratore richiede una volta al mese. In quel caso alza il limite solo per quel percorso e mantieni l’ordine dei livelli, in modo che quelli esterni aspettino più a lungo di quelli interni:
location /admin/exports/ {
proxy_read_timeout 300s;
proxy_pass http://app;
}
Alzare il limite per tutto il sito non risolve le pagine lente. Fa solo aspettare di più i visitatori prima di vedere un errore e lascia che le richieste lente occupino i worker più a lungo, peggiorando la coda per tutti gli altri.
Come il monitoraggio intercetta i 504
Un 504 raramente arriva dal nulla. La pagina è diventata un po’ più lenta ogni settimana man mano che i dati crescevano, finché un giorno ha superato il limite. È una buona notizia, perché significa che puoi vederlo arrivare.
Osserva il tempo di risposta, non solo lo stato. Uptimecheck registra il tempo di risposta di ogni controllo, suddiviso in DNS, connessione, TLS, server e download, così vedi se è rallentato il server o la rete. Un avviso di risposta lenta ti dice quando una pagina supera il limite che hai impostato, molto prima del timeout del proxy. La nostra guida su qual è un buon tempo di risposta ti aiuta a scegliere il limite.
Conferma i guasti prima di inviare avvisi. I controlli girano fino a ogni minuto da Stoccolma, Londra e New York, e ogni guasto viene confermato da una seconda località, così una singola richiesta lenta non sveglia nessuno.
Monitora direttamente le pagine lente. Ricerca, checkout, pagine dell’account e report sono i punti in cui si verificano i 504, e raramente si tratta della homepage. Aggiungi dei monitor di uptime per queste pagine, con un timeout pari a quanto un visitatore è disposto ad aspettare.
Checklist per il 504
Cronometra la richiesta: un numero tondo di secondi ti dice quale limite è scattato.
Leggi gli header e la pagina di errore per capire quale livello è andato in timeout.
Trova la pagina lenta nel log degli errori del proxy.
Cerca query lente, lock e chiamate esterne lente per quella pagina.
Controlla worker, CPU, memoria, swap e disco negli stessi minuti.
Velocizza la parte lenta, mettila in cache o spostala in un job in background.
Alza i timeout solo per i percorsi legittimamente lunghi, con i livelli esterni più lunghi di quelli interni.
Ricevi avvisi sulle risposte lente, così il prossimo 504 lo vedi quando è ancora un rallentamento.