Configuring WebSocket Server
1. Setting Server Options
| Option | Default | Description |
port | — | Listen port (omit with server) |
backlog | 511 | TCP backlog queue |
maxPayload | 100 MiB | Max message size |
clientTracking | true | Maintain wss.clients Set |
perMessageDeflate | false | Compression |
handleProtocols | — | Subprotocol selector |
verifyClient | — | Sync/async accept gate |
skipUTF8Validation | false | Skip UTF-8 check (faster, risky) |
2. Configuring Connection Limits
| Limit | Where |
| Max connections | App-level count in connection |
| Per-IP | Track IP→count map |
| File descriptors | ulimit -n ≥ N+overhead |
| Backlog | OS somaxconn |
Example: Reject over limit
const MAX = 10000;
wss.on("connection", (ws) => {
if (wss.clients.size > MAX) ws.close(1013, "server-busy");
});
3. Setting Timeout Options
| Timeout | Detail |
| Handshake | server.headersTimeout / requestTimeout |
| Idle | App heartbeat detects + closes |
| LB idle | Typically 60s; ping < that |
| TCP keep-alive | socket.setKeepAlive(true, ms) |
4. Enabling Compression
Example: permessage-deflate
new WebSocketServer({
port: 8080,
perMessageDeflate: {
zlibDeflateOptions: { chunkSize: 1024, memLevel: 7, level: 3 },
threshold: 1024, // only compress >1KB
concurrencyLimit: 10,
clientNoContextTakeover: true,
serverNoContextTakeover: true
}
});
| Option | Detail |
threshold | Min size to compress |
level | 1 (fast) – 9 (max) |
*NoContextTakeover | Trade ratio for memory |
5. Configuring Compression Options
| Parameter | Effect |
server_max_window_bits | Window size (8-15) |
client_max_window_bits | Same, for client |
server_no_context_takeover | Reset state per message |
client_no_context_takeover | Same, for client |
Warning: Without noContextTakeover, each connection holds zlib state ~256 KB → 10k clients ≈ 2.5 GB RAM.
6. Setting Client Tracking
| Mode | When |
clientTracking: true | Need broadcast |
clientTracking: false | Custom registry, save memory |
7. Configuring Verify Client
Example: Async accept
new WebSocketServer({
port: 8080,
verifyClient: async ({ req }, cb) => {
const ok = await isAuthorized(req);
cb(ok, ok ? undefined : 401, ok ? undefined : "unauthorized");
}
});
| Signature | Use |
(info) sync | Boolean accept |
(info, cb) async | cb(ok, code, reason) |
8. Handling Upgrade Request
Example: Manual upgrade
const wss = new WebSocketServer({ noServer: true });
httpServer.on("upgrade", async (req, sock, head) => {
if (!await authenticate(req)) {
sock.write("HTTP/1.1 401 Unauthorized\r\n\r\n"); sock.destroy(); return;
}
wss.handleUpgrade(req, sock, head, (ws) => wss.emit("connection", ws, req));
});
| Step | Detail |
| Inspect req | URL, headers, cookies |
| Authenticate | JWT, session |
| Authorize | RBAC, route |
handleUpgrade | Finalize WS or destroy socket |
9. Setting No Server Mode
| Benefit | Detail |
| Routing | Multiple WSS on one HTTP server |
| Auth before upgrade | Reject with HTTP status |
| Custom errors | Write HTTP response manually |
10. Configuring Environment Variables
| Var | Use |
PORT | Listen port |
WS_MAX_PAYLOAD | Limit override |
REDIS_URL | Pub/sub backplane |
JWT_SECRET | Token verify |
NODE_ENV | Toggle debug/log levels |