Votre application WebSocket fonctionne en local. En staging derrière nginx, tout semble correct — jusqu'à la minute pile : la connexion se ferme, le client tente de se reconnecter, l'utilisateur voit un flash « déconnecté ». Les logs applicatifs ne montrent aucune exception. Seul le proxy a décidé que la session était inactive.
Ce pattern — exactement 60 secondes — est l'un des diagnostics les plus rapides en hébergement web. Avant d'optimiser le handler onMessage, chronométrez la coupure : le nombre de secondes nomme souvent le coupable.
WebSocket derrière un reverse proxy
Le navigateur envoie une requête HTTP avec Upgrade: websocket. Le proxy doit transmettre les en-têtes Upgrade et Connection, ne pas appliquer un timeout HTTP classique à une connexion longue durée, et laisser passer les frames bidirectionnelles sans bufferiser indéfiniment.
| Composant | Réglage critique | Erreur fréquente |
|---|---|---|
| nginx | proxy_read_timeout | 60 s par défaut |
| HAProxy | timeout tunnel | timeout client trop court |
| AWS ALB | idle timeout | 60 s minimum configurable |
| Cloudflare | WebSockets ON | timeout edge + besoin de ping |
Le WebSocket n'est pas une requête HTTP « longue » — c'est un protocole distinct après upgrade. Le proxy doit le traiter comme tel.
Configuration nginx type
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
location /ws/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
Ajustez 3600s à votre cas — aligné sur le heartbeat applicatif, pas sur l'infini. Vérifiez aussi que le backend accepte les connexions longues et que le pare-feu intermédiaire n'impose pas sa propre limite idle.
Heartbeat applicatif : obligatoire en production
Même avec des timeouts élevés, envoyez un ping WebSocket — ou un message JSON léger — toutes les 30 à 45 secondes si un maillon de la chaîne coupe à 60 ou 100 secondes. Côté Node (ws), Python (websockets) ou Phoenix channels : activez le ping/pong natif ou implémentez-le explicitement.
Testez avec intentionnellement une minute d'inactivité utilisateur — pas seulement du trafic continu. Une session qui reste ouverte pendant un appel vidéo sans message applicatif révèle vite les limites du proxy ou du CDN.
CDN et hébergement managé
Si le WebSocket traverse Cloudflare ou un WAF, activez WebSockets dans le dashboard, vérifiez les limites de durée ou de messages selon le plan, et gardez un ping plus fréquent que le timeout edge. En origin direct sans CDN, le problème se réduit souvent à nginx ou HAProxy.
Sur PaaS (Clever Cloud, Railway, Heroku), lisez la documentation sur les connexions longues — certains routeurs imposent des plafonds fixes. Comparez les offres adaptées via notre annuaire si les connexions temps réel sont centrales à votre produit.
Le sommet : le bug n'est pas dans votre handler onMessage
Décider et avancer sans angle mort
Chronométrez d'abord l'intervalle exact de déconnexion et corrélez-le avec les timeouts documentés de chaque maillon (nginx, load balancer, CDN, PaaS). Corrigez ensuite les en-têtes Upgrade et les timeouts proxy, puis ajoutez un ping/pong plus fréquent que le timeout le plus court. Testez depuis production avec une minute d'inactivité volontaire — localhost masque souvent la couche intermédiaire. Documentez la configuration finale dans le runbook de déploiement pour éviter qu'un redeploy nginx ne réinitialise les valeurs par défaut.
Questions fréquentes
Pourquoi 60 secondes exactement ?
proxy_read_timeout nginx par défaut et valeur courante sur load balancers. Un intervalle fixe pointe vers la couche transport, pas vers une exception applicative aléatoire.
Quelles directives nginx pour WebSocket ?
HTTP/1.1, Upgrade, Connection upgrade, proxy_read/send_timeout élevés, map $http_upgrade pour les connexions mixtes HTTP et WebSocket.
Cloudflare supporte-t-il les WebSockets longue durée ?
Oui sur plans compatibles ; un ping applicatif reste recommandé pour les sessions silencieuses ou très longues.
Faut-il augmenter le timeout sans limite ?
Non — combinez un timeout aligné sur le heartbeat et un ping régulier plus fréquent que le maillon le plus strict de la chaîne.
Si votre WebSocket tombe à la minute, ne déboguez pas le message — déboguez qui ferme la connexion, et après combien de secondes exactement.
