Nginx · The edge of your stack

How do you proxy WebSocket connections through Nginx?

MediumwebsocketsupgradeproxyUpdated Oct 2026
Quiz this track

Short answer

Use HTTP/1.1 upstream, forward the Upgrade and Connection headers with a map, and raise read and send timeouts so idle WebSocket connections are not closed.

A WebSocket starts as an HTTP Upgrade request. Nginx must forward both the Upgrade and Connection headers to the backend. The Connection header is hop-by-hop, so a map avoids sending upgrade semantics on ordinary requests.

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    "" close;
}

server {
    location /ws/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;
    }
}

Production concerns

  • Sticky routing or a shared pub/sub layer is needed when multiple backend instances hold socket state
  • Load balancers and firewalls may close idle connections before Nginx does
  • The application should send heartbeats or ping frames to detect dead peers
  • Authentication usually happens during the HTTP handshake, not after the upgrade
  • An upgraded connection leaves the upstream keepalive pool and stays dedicated for the socket lifetime
Hardcoding Connection: upgrade for every proxied request breaks normal HTTP behavior. Use a map so only requests carrying an Upgrade header get the upgrade values.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1Why is HTTP/1.1 required for WebSocket proxying?
  2. 2What happens if the proxy_read_timeout is shorter than the idle time?
  3. 3How do multiple backend instances handle WebSocket sessions?
  4. 4Where should WebSocket authentication happen?

Say it in the interview

I set HTTP/1.1 to the upstream and use a map to forward Upgrade and Connection only when the client requested an upgrade. I raise read and send timeouts, disable buffering for that path, and make sure the load balancer's idle timeout is at least as generous. With multiple instances I need sticky routing or a shared pub/sub layer.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Nginx mock interview and get scored feedback on depth, clarity and confidence.