504 Gateway Timeout : backends lents, timeouts et 502 vs 503 vs 504
Un 504 Gateway Timeout signifie qu'un proxy a atteint votre backend, a attendu une réponse, et a abandonné avant qu'elle n'arrive. Rien n'a planté et rien n'a refusé la requête : quelque chose derrière le proxy est plus lent que ce que le proxy est disposé à attendre.
Ce que rapporte un 504
La RFC 9110 définit 504 pour un serveur agissant comme passerelle ou proxy qui n'a pas reçu de réponse à temps d'un serveur amont auquel il avait besoin d'accéder. Le mot « à temps » est défini par la configuration, pas par la spécification, donc un 504 est toujours une déclaration sur deux choses à la fois : la lenteur du backend, et la limite à laquelle le proxy était réglé.
Cela a une conséquence pratique importante. Quand un proxy renvoie 504, le backend continue généralement de travailler sur la requête. La connexion vers le client a disparu, mais la requête lente tourne toujours, le rapport est toujours en cours de génération, et les ressources sont toujours retenues. C'est pourquoi une vague de 504 aggrave souvent un serveur : chaque requête abandonnée laisse du travail derrière elle, et la file d'attente grossit plus vite qu'elle ne se vide.
504 face à 502 face à 503
| 502 Bad Gateway | 503 Service Unavailable | 504 Gateway Timeout | |
|---|---|---|---|
| Ce qui s'est passé | Le backend a donné une réponse invalide ou a fermé la connexion | Le serveur a refusé le travail délibérément | Le backend a accepté le travail et n'a jamais répondu à temps |
| État du backend | En panne, en train de planter, ou parle le mauvais protocole | En ligne, mais surchargé ou en maintenance | En ligne et occupé, toujours en train de traiter |
| Vitesse de réponse | Généralement immédiate | Généralement immédiate | Lente, arrive à la limite du timeout |
| Ligne de journal typique | connect() failed ou upstream prematurely closed connection | Règle de maintenance, ou aucun amont sain | upstream timed out (110: Connection timed out) |
Retry-After | Pas habituel | Courant et recommandé | Pas habituel |
| Premier endroit où regarder | Le processus backend tourne-t-il ? | Capacité, indicateurs de maintenance, vérifications de santé | Requêtes lentes et dépendances lentes |
En pratique, un 502 échoue vite, un 503 refuse poliment, et un 504 vous fait d'abord attendre. Le guide dédié au 502 et l'aperçu des 5xx couvrent les deux autres en détail.
Pourquoi le backend est trop lent
- Requêtes de base de données lentes. Un index manquant, une requête qui a grossi avec les données, un motif N+1 dans une boucle, ou une contention de verrou sous concurrence. La cause la plus courante de toutes.
- Appels tiers lents. Une requête API sortante sans son propre timeout hérite de la pire journée du service distant et la transmet à vos visiteurs.
- Démarrages à froid. La première requête après une montée en charge, un démarrage de conteneur ou une période d'inactivité paie pour l'initialisation, l'établissement de connexion et le réchauffement du cache tout à la fois.
- Travail véritablement lourd sur une requête web. La génération de rapports, les exports, le traitement d'images ou les imports en masse traités de façon synchrone finiront par dépasser tout timeout raisonnable.
- Contention de ressources. La saturation CPU, la pression mémoire et le swap ralentissent chaque requête, donc les plus lentes franchissent la limite en premier.
- Timeouts réglés trop courts. Si un point de terminaison a légitimement besoin de plus de temps que ce que le proxy autorise, la configuration est le bug, pas le code.
- Problèmes réseau entre les sauts. La perte de paquets ou les délais de résolution DNS pour l'adresse amont ajoutent une latence qui n'apparaît pas dans les chronométrages applicatifs.
Comment diagnostiquer et corriger un 504
- Mesurez le temps jusqu'à l'erreur. Le délai avant un 504 correspond généralement au timeout configuré, ce qui vous indique quel saut l'a produit :
Un 504 à presque exactement 60 secondes pointe vers un timeout de lecture par défaut du proxy. Un à 30 ou 100 secondes pointe vers le composant configuré avec ce nombre, souvent un CDN plutôt que votre propre proxy.curl -sS -o /dev/null -w "%{http_code} %{time_total}s\n" https://example.com/slow-page - Déterminez si c'est un seul point de terminaison ou tous. Une seule URL lente est un problème applicatif. Tout lent en même temps est une saturation de ressources ou une dépendance défaillante.
- Lisez le journal d'erreurs du proxy. Avec nginx, la ligne est explicite :
Elle nomme l'amont et la phase, ce qui distingue une connexion lente d'une réponse lente.[error] upstream timed out (110: Connection timed out) while reading response header from upstream, upstream: "http://127.0.0.1:8080/" - Chronométrez le backend directement, sans le proxy. Si la même requête met 90 secondes contre l'origine, le proxy rapporte la vérité et la correction appartient à l'application.
- Profilez le chemin lent. Vérifiez le journal des requêtes lentes, puis les traces applicatives. La plupart des 504 se résolvent à une seule requête ou un seul appel sortant.
- Corrigez la cause avant le timeout. Ajoutez l'index, mettez en cache le résultat coûteux, ou déplacez le travail véritablement long vers une tâche d'arrière-plan qui répond immédiatement et rapporte sa progression séparément.
- N'augmentez le timeout que quand le travail est légitimement long, et augmentez-le de façon cohérente sur chaque saut. Une limite CDN de 30 secondes rend inutile un timeout d'origine de 120 secondes.
- Réglez des timeouts sur vos propres appels sortants pour qu'une dépendance lente échoue vite avec une erreur claire plutôt que de consommer un worker jusqu'à ce que le proxy abandonne.
Le temps de réponse est l'alerte précoce
Un 504 est l'état final d'un ralentissement qui se construisait depuis un moment. Les temps de réponse dérivent d'une demi-seconde à deux secondes puis à dix, et personne ne le remarque jusqu'à ce que des requêtes commencent à franchir la limite. Une vérification HTTP programmée enregistre le temps de réponse de chaque vérification aux côtés du code de statut, donc la tendance est visible comme un graphique bien avant le premier timeout, et l'alerte arrive au premier vrai échec plutôt qu'après que la file de support s'est remplie. Vérifier depuis plusieurs régions aide aussi, car une route rapide depuis un continent et lente depuis un autre pointe vers le chemin réseau ou la configuration de bordure plutôt que vers votre base de données.