Errore 504 Gateway Timeout: trovare cosa rallenta
· 6 min di lettura
Cosa significa l’errore
Con un 504, il server web davanti (nginx, Apache, un bilanciatore di carico, una CDN) si arrende con l’applicazione dietro: la richiesta è stata passata e il backend stava ancora lavorando quando il contatore davanti è arrivato a zero. La differenza con il 502 Bad Gateway: il backend è raggiungibile, è solo troppo lento. Timeout abituali: 60 secondi in nginx (fastcgi_read_timeout, proxy_read_timeout), 60 secondi in Apache (ProxyTimeout) e 100 secondi su Cloudflare, che nel piano gratuito non si possono cambiare.
Alzare il timeout è raramente la soluzione. Qualcosa ci mette troppo, e quel qualcosa va trovato.
Cause frequenti
- Una query SQL lenta. Un plugin di WordPress che conta le righe di una tabella enorme a ogni pagina, un indice mancante, una tabella
wp_optionspiena di transient scaduti. Ogni richiesta aspetta, e sotto carico le attese si sommano. - Una chiamata esterna che resta appesa. L’applicazione interroga un fornitore di pagamenti, un servizio di posta, un’API meteo o un server di licenze, e quel servizio è lento o down. Senza un timeout su quella chiamata, la tua pagina aspetta insieme a lui.
- Troppo pochi worker. Tutti i worker di PHP-FPM sono intrappolati in richieste lente; le nuove si mettono in coda finché il server davanti si arrende. Visto dall’esterno è un timeout, anche se ogni singola richiesta, da sola, sarebbe veloce.
- Cron o backup in primo piano. Un plugin di backup, un’importazione, una sitemap da 50.000 URL: generati dentro una richiesta web, superano qualsiasi timeout.
- I/O del disco o swap. Al server manca memoria, usa lo swap e tutto diventa dieci volte più lento: carico alto, processore poco occupato.
- Rete tra il server davanti e il backend. Un bilanciatore di carico in un data center e il backend in un altro, un firewall che scarta pacchetti in silenzio. Raro, ma un 504 a ogni richiesta con un backend inattivo punta lì.
Se sei un visitatore
Ricarica tra un minuto. Se il sito è lento invece che down, prova un’altra pagina; forse la colpa è di una sola pagina pesante.
Se il sito è tuo: verifica prima
Apri il Website down checker: mostra il codice HTTP e il tempo di risposta visti dall’esterno. Un sito che oggi risponde in 30 secondi domani, sotto carico, dà un 504.
Sul tuo server, il tempo perso si cerca qui:
# ci sono timeout nei log?
sudo tail -n 30 /var/log/nginx/error.log | grep -E 'timed out|timeout'
# cosa sta facendo PHP? (richiede pm.status_path nel pool)
curl -s 'http://127.0.0.1/fpm-status?full' | grep -E 'state|request URI|duration' | head -40
# MySQL/MariaDB: quali query girano e da quanto?
sudo mysql -e 'SHOW FULL PROCESSLIST;'
# memoria e swap
free -m
vmstat 1 5
Una lista piena della stessa query o colonne si/so diverse da zero fanno il nome della causa.
Soluzioni sul tuo server
1. Attivare il log delle query lente e correggere la query
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
Dopo qualche minuto, sudo mysqldumpslow -s t /var/log/mysql/slow.log | head elenca le query peggiori. Crea l’indice mancante o sostituisci il plugin che lancia la query. Su WordPress, la tabella delle opzioni gonfia è un classico:
wp transient delete --all
wp db query "SELECT option_name, LENGTH(option_value) AS size FROM wp_options WHERE autoload='yes' ORDER BY size DESC LIMIT 20;"
Tutto ciò che pesa centinaia di kilobyte e viene caricato in automatico a ogni richiesta è un candidato alla rimozione.
2. Dare un timeout alle chiamate esterne
Ogni chiamata HTTP della tua applicazione ha bisogno di un timeout proprio, più corto di quello del server web. In PHP con cURL: CURLOPT_CONNECTTIMEOUT a 5 e CURLOPT_TIMEOUT a 10. Su WordPress, wp_remote_get() accetta un argomento timeout; molti plugin lo lasciano al valore predefinito e aspettano all’infinito. Se un servizio di terzi è down, la pagina deve uscire in versione ridotta (il modulo senza la tariffa di spedizione in tempo reale), non morire.
3. Togliere i processi lunghi dalla richiesta
Backup, importazioni, esportazioni, sitemap grandi e invii di e-mail vanno in un cron job o in una coda, non in una pagina. Su WordPress, disattiva lo pseudo-cron e installa quello vero:
// 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. Regolare i timeout, con misura
Se una sola pagina ha davvero bisogno di più tempo (un’esportazione dall’area admin, un report), alza il timeout solo per lei, non a livello globale:
location = /wp-admin/export.php {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_read_timeout 300;
}
Apache con PHP-FPM: ProxyTimeout 300 dentro un blocco <Location>. Metti max_execution_time di PHP allo stesso valore; altrimenti PHP si arrende per primo con un 500. Poi sudo nginx -t && sudo systemctl reload nginx.
5. Smettere di usare lo swap
ps aux --sort=-%mem | head
Se ogni worker di PHP-FPM occupa 150 MB e ne lanci 30 su un server da 4 GB, i conti non tornano. Abbassa pm.max_children, aggiungi memoria o sistema il plugin che la divora. Un server che non usa lo swap è un server i cui 504 per lo più spariscono.
6. Mettere una cache
Una cache delle pagine (la cache FastCGI di nginx, un plugin di WordPress, Varnish) serve i visitatori di ritorno senza toccare PHP né il database. La maggior parte dei 504 sotto carico sparisce appena la home page e le pagine più visitate escono da lì.
Se il problema è presso il tuo provider di hosting
Su un hosting condiviso puoi correggere query lente e plugin, ma non i timeout del server né il carico dei vicini. Invia al tuo provider di hosting:
Buongiorno, il mio sito example.com restituisce “504 Gateway Timeout” da circa le 16:00 (UTC). Pagine che prima si caricavano in meno di due secondi adesso superano il timeout. Non ho modificato nulla. Potete verificare se il server del database o il pool PHP del mio account è sovraccarico, oppure se un altro account sullo stesso server sta generando molto carico, e dirmi cosa trovate?
Perché non succeda di nuovo
Un 504 è un sito lento diventato ancora più lento, e il tempo di risposta si misura molto prima del timeout. Le verifiche del sito registrano il tempo di risposta a ogni passaggio; mettici un avviso e vedrai la tendenza settimane prima che i visitatori vedano un errore. Il monitoraggio server aggiunge carico, memoria e swap dall’interno.
Down? Interveniamo. Sul tuo server o su un hosting condiviso con accesso SSH, il Deep Fix, l’intervento approfondito, trova la query lenta o la chiamata appesa e la corregge, 24 ore su 24, anche nel fine settimana, a blocchi di 15 minuti, prezzo visibile prima dell’ordine, la stima è il prezzo massimo; il Quick Fix, a prezzo fisso, riavvia un servizio fermo.
E adesso
Verifica dall’esterno
Il sito è down per tutti o solo per te, e cosa risponde il server? Gratis, senza registrazione.
Website down checkerDown? Interveniamo.
Sul tuo server o su un hosting condiviso con accesso SSH: Quick Fix a prezzo fisso per le cause più comuni, Deep Fix fatturato a blocchi di 15 minuti per tutto il resto, 24/7. Prezzo visibile prima dell’ordine.
Ordina un interventoAltre guide
- Sito non raggiungibile: cosa fare nei primi 15 minuti
- Server down o non raggiungibile: cosa controllare e in che ordine
- Errore 500 Internal Server Error: trovare la causa nei log e rimettere online il sito
- Errore 502 Bad Gateway: trovare la causa e risolverlo
- Errore 503: sovraccarico, manutenzione o limite dell’hosting?
- Errore 521 e 522 di Cloudflare: il server di origine non risponde
- DNS_PROBE_FINISHED_NXDOMAIN: il dominio non risponde più
- ERR_CONNECTION_REFUSED: il server rifiuta la connessione
- ERR_CONNECTION_TIMED_OUT: il server non risponde in tempo
- Cosa significa “La connessione non è privata” e come risolverlo
- ERR_SSL_PROTOCOL_ERROR: la connessione sicura fallisce prima del certificato
- ERR_TOO_MANY_REDIRECTS: trovare il ciclo di reindirizzamenti e chiuderlo
- Errore 403 Forbidden: cosa blocca l’accesso al tuo sito