A support chat deployed in Node.js works perfectly in staging: twenty testers, instant latency. In production on the same VPS, 300 connected agents — the server hits too many open files, nginx returns 502, and connections drop every 60 seconds because nobody raised the default proxy_read_timeout.
WebSocket is not slightly longer HTTP. It is a different resource model: persistent connections, memory per client, heartbeats, and often broadcast that amplifies every message. Hosting real time without a plan turns product success into a predictable infrastructure incident.
WebSocket vs HTTP: what an open connection really costs
| Resource | Short HTTP request | Open WebSocket |
|---|---|---|
| File descriptors | 1 then released | 1 held for hours |
| App server RAM | Recycled worker pool | Buffer + session state |
| CPU | Spike on request | Heartbeat + continuous messages |
| Proxy | Easy stateless | Upgrade + timeout tuning |
| Scale-out | Simple horizontal | Sticky or pub/sub required |
Rule of thumb: estimate 50 KB–200 KB RAM per connection by stack (Node, Go, Elixir vary). 5,000 connections × 100 KB ≈ 500 MB — before business logic.
The first killer number is usually not CPU — it is
ulimit -nand proxy timeout.
Reverse proxy: nginx in front of the real-time app
Minimal nginx config:
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
Often missed: global nginx worker_connections vs WebSocket connections; TLS termination at proxy — some hosts cap simultaneous SSL connections; HTTP/2 on public client, HTTP/1.1 Upgrade to upstream.
See also WebSocket proxy timeout and Nginx or Apache.
Horizontal scaling: sticky vs broker
Option A — Sticky sessions. Load balancer pins client to same node. Simple, fragile if node dies (reconnect storm).
Option B — Redis pub/sub or Socket.IO adapter. Messages routed across nodes; connections spread. Required from 2+ instances.
Option C — Managed service (Pusher, Ably, managed Mercure hub). Outsourced complexity; cost per message.
For a serious MVP, Option B on two small VPS beats one large server without pub/sub.
Hosting: questions for the provider
Before choosing, ask whether long connections are allowed (shared hosting often cuts them), what the file descriptor limit is, whether UDP or QUIC are filtered for WebTransport, whether the L7 load balancer supports WebSocket Upgrade, and whether anti-DDoS can falsely block slow connections.
Cloud VPS (Hetzner, OVH, Scaleway) + nginx remains the most predictable combo for self-hosted WebSocket.
Heartbeats, reconnect, and observability
Send application ping/pong every 30 s to detect dead connections. Apply exponential backoff client-side to avoid thundering herd on server restart. Measure active connections, messages/s, broadcast 99th-percentile latency. Plan graceful shutdown: stop accept → drain 30 s.
The peak: real time scales on connections, not page views
Selling "live chat" without max connections, proxy timeout, and pub/sub plan means selling a feature that does not survive first traction.
Decide and move forward without blind spots
First calculate max connections × RAM and check ulimit. Configure nginx timeouts before launch. Test reconnect after deploy — not happy path only. Plan Redis pub/sub before the second server. Set up an active connections dashboard with alert at 80% threshold.
Explore VPS and cloud in our directory and compare tool.
Frequently asked questions
How many WebSocket connections can a server hold?
Depends on RAM per connection, file descriptors, and nginx. Thousands of idle connections are possible; far fewer if each message triggers heavy work.
Do you need sticky sessions behind a load balancer?
Yes if state lives in process memory. Otherwise use Redis pub/sub or a dedicated hub to share state across nodes.
Does shared hosting support WebSocket?
Often partially or with short timeouts (30–60 s). Check host docs — some panels kill long connections.
Nginx or Apache in front of Node.js WebSocket?
Nginx is more common with Upgrade headers and suitable proxy_read_timeout (often 3600 s or more). Apache mod_proxy_wstunnel works but is less common in real-time production.
Real time is sized on open connections — not last month's unique visitors.