504 Gateway Timeout
En anglais : 504 Gateway Timeout
Réponse rapide
Le serveur frontal (nginx, Apache, CDN) a attendu PHP trop longtemps et a abandonné. Identifiez le script lent dans le journal, puis allongez les délais du proxy et de PHP, ou découpez la tâche en lots.
Après de longues secondes d’attente, le navigateur affiche « 504 Gateway Timeout » (« 504 Gateway Time-out » avec nginx). La page ne s’est pas chargée, mais ce n’est pas forcément un plantage : le serveur a continué de travailler pendant que son intermédiaire, lui, a cessé d’attendre. L’erreur apparaît le plus souvent sur une action longue : import, sauvegarde, génération de rapport, enregistrement d’une très grosse page, appel d’API externe.
Ce que signifie cette erreur
Une réponse 504 est émise par un passerelle ou proxy qui transmet votre requête à un serveur en amont et n’obtient pas de réponse dans le délai qui lui est imparti. WordPress est ici le serveur en amont : il n’a pas encore répondu, donc il ne peut pas avoir produit l’erreur lui-même (le libellé « Gateway Timeout » existe pourtant dans get_status_header_desc(), wp-includes/functions.php, comme dans la classe WP_Http pour les requêtes sortantes). Plusieurs maillons peuvent déclarer forfait :
- nginx devant PHP-FPM : la directive
fastcgi_read_timeoutvaut 60 secondes par défaut, et le journal indique « upstream timed out (110: Connection timed out) while reading response header from upstream » ; - Apache avec
mod_proxy_fcgiou en proxy inverse : ce sontProxyTimeoutetTimeoutqui comptent ; - Un CDN ou un répartiteur de charge : le délai est fixé chez eux, souvent plus court que le vôtre, et vos réglages serveur n’y changent rien ;
- PHP lui-même : si
max_execution_timeourequest_terminate_timeouttranche avant le proxy, c’est une autre erreur qui s’affiche (voir la fiche temps d’exécution dépassé).
Un 504 se distingue du 502 (la réponse du serveur en amont est invalide ou la connexion est refusée) et du 503 (service indisponible ou saturé) : ici, la connexion est établie, mais la réponse n’arrive pas à temps.
Diagnostic rapide
| Symptôme / constat | Cause probable | À vérifier |
|---|---|---|
| Échec après une durée constante (60 s, 100 s…) | Délai d’un proxy ou d’un CDN atteint | Chronométrer l’échec avec curl -w ; réglages nginx, Apache, CDN |
| Uniquement sur un import, une sauvegarde, un export | Tâche longue exécutée dans la requête web | Découper en lots ou exécuter avec WP-CLI |
| Toutes les pages lentes puis 504 | Serveur saturé ou requête SQL lente | Journal des requêtes lentes PHP et MySQL ; charge du serveur |
| Échec uniquement quand une extension précise est active | Appel à une API externe qui ne répond pas | Journal PHP, test de la requête sortante (fiche cURL 28) |
| 504 avec la mention d’un CDN ou d’un WAF | Le CDN n’a pas reçu de réponse de l’origine | Accéder directement à l’origine, journal de l’origine |
| Le script va au bout malgré le 504 | Le travail continue après la coupure du proxy | Résultat en base de données ; journal PHP-FPM |
Les causes les plus fréquentes
- Une tâche trop longue exécutée dans une requête web : import de milliers de lignes, régénération de miniatures, sauvegarde.
- Un délai de proxy trop court par rapport au travail demandé (60 secondes par défaut sur nginx).
- Une requête externe qui ne répond pas : API de paiement, service d’e-mailing, serveur de licences, vérification de mises à jour.
- Une base de données lente ou verrouillée : requêtes sans index, tables énormes, options chargées automatiquement trop nombreuses.
- Un serveur sous-dimensionné ou saturé : les requêtes attendent un processus PHP libre.
- Un CDN ou un WAF dont le délai est plus court que celui de votre serveur.
Solutions pas à pas
Sauvegardez fichiers et base avant de toucher à la configuration, et testez-la avant de recharger un service (nginx -t ou apachectl configtest). Du moins invasif au plus technique :
1. Mesurer le délai et trouver le maillon
Un délai constant trahit un proxy : mesurez le temps écoulé jusqu’à l’échec.
curl -s -o /dev/null -w '%{http_code} en %{time_total} s\n' https://www.exemple.fr/wp-admin/admin-ajax.php?action=mon_action
Si l’échec survient toujours à la même seconde (60, 100, 120…), cherchez le réglage correspondant. Puis lisez le journal d’erreurs du serveur web à l’heure du test :
sudo tail -n 50 /var/log/nginx/error.log
sudo tail -n 50 /var/log/apache2/error.log
Pour croiser ces journaux avec ceux de PHP et de WordPress, l’article centraliser les logs nginx, PHP et WordPress détaille une méthode.
2. Alléger la tâche plutôt que d’allonger le délai
Allonger les délais masque le problème : une page qui met plus d’une minute à répondre bloque un processus PHP pendant tout ce temps. Quand c’est possible, traitez par lots (quelques dizaines d’éléments par appel, avec reprise), ou lancez la tâche en ligne de commande, qui n’a aucun proxy devant elle :
wp cron event run --due-now
wp media regenerate --yes
wp import export.xml --authors=skip
(wp import demande l’extension WordPress Importer.) La méthode de découpage est détaillée dans traiter 50 000 éléments sans timeout, et le cas d’un proxy amont trop court dans 504 Gateway Timeout sur un import volumineux.
3. Allonger les délais de nginx
Limitez l’allongement à la zone concernée plutôt qu’à tout le site :
# bloc server : uniquement l'administration
location ^~ /wp-admin/ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_read_timeout 300s;
fastcgi_send_timeout 300s;
}
Adaptez le nom de l’include et le socket à votre installation, puis sudo nginx -t && sudo systemctl reload nginx. Si nginx est lui-même derrière un autre proxy, réglez aussi proxy_read_timeout sur celui-ci.
4. Allonger les délais d’Apache
# dans le VirtualHost
ProxyTimeout 300
Timeout 300
ProxyTimeout s’applique aux échanges avec PHP-FPM via mod_proxy_fcgi ; Timeout (300 par défaut sous Debian) borne les entrées-sorties de la connexion. Rechargez avec sudo systemctl reload apache2.
5. Aligner PHP sur le proxy
Un délai de proxy plus long ne sert à rien si PHP coupe avant. Alignez la limite de PHP et celle du pool PHP-FPM :
; php.ini ou .user.ini
max_execution_time = 300
; pool PHP-FPM (ex. /etc/php/8.2/fpm/pool.d/monsite.conf)
request_terminate_timeout = 300s
Sur un mutualisé, ces valeurs se règlent dans le panneau (rubrique PHP) ou via .user.ini à la racine du site. Rechargez PHP-FPM : sudo systemctl reload php8.2-fpm.
6. Trouver le script ou la requête lente
Dans le pool PHP-FPM, activez le journal des requêtes lentes : il écrit la pile d’appels des scripts qui dépassent le seuil.
request_slowlog_timeout = 10s
slowlog = /var/log/php8.2-fpm-slow.log
Côté base de données, activez le journal des requêtes lentes de MySQL ou MariaDB (slow_query_log et long_query_time), ou installez temporairement l’extension Query Monitor pour voir quelle requête, quel crochet ou quel appel HTTP prend le temps.
7. Si un CDN ou un WAF est devant
Testez en contournant le CDN (accès direct à l’IP d’origine avec un en-tête Host, ou en désactivant temporairement le proxy). Si l’erreur disparaît, le délai du CDN est en cause : il est souvent fixe selon l’offre (de l’ordre de 100 secondes chez certains), donc la seule vraie solution est de rendre la tâche plus courte ou de la lancer hors requête web.
Prévenir l’erreur
- Ne lancez jamais une tâche de plusieurs minutes dans une requête web : planifiez-la avec un cron système ou découpez-la en lots avec reprise.
- Donnez un délai explicite aux appels sortants (
wp_remote_get()avectimeout) pour qu’une API externe lente ne bloque pas la page. - Gardez le journal des requêtes lentes de PHP-FPM actif : il signale la dérive avant l’incident.
- Surveillez la taille de la table des options et des tables volumineuses, et ajoutez les index manquants.
- Documentez les délais de chaque maillon (CDN, proxy, PHP) pour savoir lequel ajuster.
Puis-je simplement mettre un délai énorme ?
Techniquement oui, mais c’est déconseillé : chaque requête longue immobilise un processus PHP, et quelques-unes suffisent à saturer le site. Réservez l’allongement à une zone précise (l’administration, une route d’import) et préférez découper la tâche.
Le travail s’est-il quand même terminé malgré l’erreur 504 ?
Souvent oui : le proxy abandonne la connexion, mais PHP continue jusqu’à sa propre limite. Vérifiez le résultat (articles importés, fichier généré) avant de relancer, sous peine de créer des doublons.
Pourquoi la 504 revient-elle avec un hébergement qui n’affiche aucun réglage ?
Sur un mutualisé, les délais sont fixés par l’hébergeur. Demandez-lui la valeur appliquée à votre offre, ou exécutez la tâche avec WP-CLI si l’accès SSH est disponible.
La 504 est-elle liée à un appel externe ?
Elle peut l’être : si WordPress attend une API qui ne répond pas, la page entière attend. Dans ce cas, le journal montre souvent aussi l’erreur cURL 28.