Code de statut 499 : ce que nginx entend par client closed request
Un 499 dans un journal nginx signifie que le client a fermé la connexion avant que nginx n'ait fini d'envoyer une réponse. Cela ne fait pas partie du standard HTTP officiel ; nginx l'a inventé purement pour son propre journal d'accès afin que les opérateurs puissent distinguer « le client a abandonné » de tout autre type d'échec.
Ce que signifie le code de statut 499
499 Client Closed Request est spécifique à nginx et n'est jamais défini dans aucune RFC. Les codes au-dessus de 99 et en dessous de 600 sont réservés aux lignes de statut HTTP en général, mais 499 est la propre convention de nginx, journalisée quand nginx détecte que la connexion du client a chuté alors qu'il attendait encore que l'application upstream réponde, ou alors qu'il envoyait encore le corps de la réponse au client. La forme la plus courante en pratique est un upstream lent combiné à un client, un onglet de navigateur, ou un équilibreur de charge dont le propre délai est plus court que le temps que le serveur allait prendre, donc le client raccroche en premier.
Comment cela apparaît dans les journaux
Vous ne verrez jamais 499 comme un code de statut renvoyé à un quelconque client, navigateur, curl, ou autre, parce que par définition le client est déjà parti au moment où nginx l'aurait envoyé. Cela n'existe que dans le propre journal d'accès de nginx :
10.0.0.12 - - [19/Sep/2026:14:02:11 +0000] "GET /api/report HTTP/1.1" 499 0 "-" "python-requests/2.31"
La taille de réponse de 0 octet et le timing par rapport au temps de réponse connu de votre upstream sont les deux détails les plus utiles : un 499 qui atterrit systématiquement juste autour du délai de votre upstream, sans rien renvoyé, pointe carrément vers « le backend était trop lent et quelque chose a abandonné d'attendre ».
Ce qui provoque un 499
- Une application upstream lente. Le backend met plus de temps à répondre que ce qu'un client ou un intermédiaire est disposé à attendre, que ce soit une requête de base de données lente, un appel d'API externe, ou un calcul réellement lourd.
- Un délai côté client plus court que ce dont le serveur a besoin. Un onglet de navigateur fermé, une application mobile qui abandonne sur une connexion instable, ou le propre délai d'une bibliothèque cliente HTTP qui se déclenche avant que la réponse n'arrive.
- Un équilibreur de charge ou un proxy upstream qui dépasse son délai en premier. Si quelque chose se trouve entre le vrai utilisateur final et nginx, son propre délai peut déclencher une déconnexion que nginx journalise comme 499, même si le vrai utilisateur final n'a jamais explicitement annulé quoi que ce soit.
- Un utilisateur qui quitte la page ou rafraîchit. Quelqu'un qui quitte une page qui se charge lentement, ou qui appuie sur rafraîchir avec impatience, ferme la connexion en cours avant que nginx n'ait fini.
- Des valeurs de délai incohérentes à travers la chaîne. Un client, un CDN, un équilibreur de charge, et nginx lui-même peuvent chacun avoir un délai différent, et celui qui est le plus court détermine quand la déconnexion se produit, indépendamment de ce pour quoi les autres sont configurés.
Pourquoi cela n'apparaît jamais dans un navigateur
499 n'est pas une réponse, c'est une note que nginx se fait à lui-même à propos d'une réponse qu'il n'a jamais fini d'envoyer. Un utilisateur dont l'onglet a produit un 499 dans vos journaux ne voit rien du tout : pas de page d'erreur, pas de code de statut, juste une page qui a arrêté de se charger ou un indicateur de chargement qui ne s'est jamais résolu, parce qu'il n'y avait pas de réponse pour que le navigateur l'affiche. C'est exactement pourquoi se fier aux erreurs signalées par les utilisateurs manque entièrement ces cas ; le seul endroit où un 499 est visible est le propre journal d'accès du serveur.
Comment corriger et réduire les 499
Il n'existe pas un seul réglage qui élimine les 499, puisque la cause sous-jacente est une course entre le client qui abandonne et le serveur qui termine, et la correction dépend de quel côté de cette course est réellement cassé. Commencez par établir si l'upstream est systématiquement lent pour la route affectée, ou si les déconnexions se regroupent autour d'un client, d'un réseau, ou d'un intermédiaire, puisque cela pointe vers des corrections différentes.
- Examinez d'abord le temps de réponse de l'upstream, puisqu'un backend lent est la cause sous-jacente la plus courante. Regardez combien de temps les requêtes affectées ont réellement pris en amont, pas seulement que nginx a journalisé un 499.
- Alignez les valeurs de délai à travers toute la chaîne, délibérément, plutôt que de laisser en place la valeur par défaut de chaque couche : le client, le CDN, l'équilibreur de charge, et les propres
proxy_read_timeoutetproxy_connect_timeoutde nginx devraient être fixés avec une compréhension claire de lequel est censé se déclencher en premier. - Envisagez
proxy_ignore_client_abortsi laisser l'upstream terminer son travail même après que le client s'est déconnecté compte pour votre application, par exemple pour terminer une écriture qui ne devrait pas être laissée à moitié faite :
Cela n'empêche pas l'entrée de journal 499 pour la déconnexion d'origine ; cela change si nginx laisse la requête upstream continuer indépendamment.proxy_ignore_client_abort on; - Accélérez le travail upstream réel là où la cause racine est réellement un point de terminaison lent, puisqu'aucun ajustement de délai ne corrige à lui seul un backend qui prend trop de temps ; profilez les requêtes ou appels lents précis derrière la route affectée.
- Traitez un taux de 499 croissant comme un signal réel, pas comme du bruit de journal à filtrer, puisque cela signifie généralement soit que votre application est devenue plus lente, soit que votre configuration de délai est mal alignée quelque part dans la chaîne.
Comment empêcher que cela ne devienne une panne
Comme le 499 n'atteint jamais le client comme une erreur visible, il est facile pour un point de terminaison réellement lent de passer inaperçu jusqu'à ce que quelqu'un lise les journaux d'accès, même pendant que de vrais utilisateurs abandonnent tranquillement leurs requêtes. Une vérification HTTP programmée mesure le temps de réponse réel directement contre le point de terminaison et alerte quand il se dégrade, détectant le ralentissement qui produit les 499 avant qu'il ne se transforme en requêtes qui échouent purement et simplement. La surveillance depuis plusieurs emplacements aide aussi à distinguer un backend réellement lent d'un délai qui ne se déclenche que pour des clients sur un chemin réseau particulier.
Erreurs associées
Voir 504 Gateway Timeout pour l'équivalent standard visible du client quand nginx lui-même abandonne d'attendre l'upstream plutôt que le client qui abandonne en premier, l'aperçu des 4xx pour la famille standard d'erreurs client, et 429 Too Many Requests pour un type différent de rejet lié au débit plutôt qu'au timing.
Questions fréquentes
499 est-il un vrai code de statut HTTP ?
Non. C'est la propre convention de journalisation de nginx pour un client qui s'est déconnecté avant que la réponse ne se termine, et il n'est jamais envoyé sur le réseau à un quelconque client puisque le client est déjà parti au moment où il serait envoyé.
Pourquoi mon outil de surveillance ne voit-il jamais de 499 ?
Une vérification de surveillance est elle-même un client, et si c'est elle qui abandonne sur une réponse lente, elle rapportera sa propre erreur de délai dépassé, pas 499, puisqu'elle ne reçoit jamais de réponse HTTP dont lire un code de statut. Le 499 n'apparaît jamais que dans la propre entrée de journal d'accès du serveur pour cette requête.
Un 499 signifie-t-il que mon serveur a planté ?
Non. Cela signifie précisément que le serveur travaillait encore, ou était sur le point de commencer à travailler, quand le client s'est déconnecté. Un plantage produirait typiquement un 502 ou un 500 à la place, une fois que quelque chose a répondu.
Puis-je arrêter le traitement upstream quand un client se déconnecte ?
Par défaut, nginx arrêtera généralement d'attendre l'upstream une fois que le client est parti, mais le comportement exact dépend de vos réglages de proxy ; proxy_ignore_client_abort on dit à nginx de laisser la requête upstream continuer plutôt que de l'abandonner.
Quelle est la correction la plus courante pour des 499 fréquents ?
Aligner les valeurs de délai à travers le client, tout proxy ou équilibreur de charge intermédiaire, et nginx lui-même, combiné avec le traitement de ce qui rend l'upstream lent au départ. Aucun des deux seul ne résout généralement un schéma persistant.