WebSocket Sticky Sessions — Complete Guide
In this tutorial, you will learn about WebSocket Sticky Sessions. We cover key concepts, practical examples, and best practices to help you master this topic.
Sticky sessions (session affinity) ensure that all WebSocket frames from a client are routed to the same server instance. This is required because WebSocket state (rooms, subscriptions) is typically stored in server memory.
What You'll Learn
- Why WebSocket needs sticky sessions
- Load balancer sticky session configuration
- Cookie-based vs source IP affinity
- Redis-backed session stores
- Stateless WebSocket with pub/sub
Why It Matters
Without sticky sessions, a WebSocket client may reconnect to a different server after a load balancer routing change, losing all in-memory state. Sticky sessions prevent this by pinning clients to servers.
Real-World Use
AWS ALB supports sticky sessions via cookies. Nginx uses ip_hash for source IP affinity. Kubernetes ingress controllers support session affinity for WebSocket backends.
flowchart LR
Client[Client] --> LB[Load Balancer]
LB -->|Sticky Cookie| ServerA[WebSocket Server A]
LB -..->|No sticky| ServerB[WebSocket Server B]
ServerA --> Redis[Redis Pub/Sub]
ServerB --> Redis
Client2[Client 2] --> LB
LB -->|Sticky Cookie| ServerB
Teacher Mindset
Sticky sessions are a workaround for stateful WebSocket servers. The better solution is stateless WebSocket using a shared pub/sub backend. Use sticky sessions for simple deployments and pub/sub for horizontal scaling.
Code Examples
# Example 1: Nginx sticky sessions with ip_hash
upstream websocket_backend {
ip_hash;
server ws1.example.com:8080;
server ws2.example.com:8080;
server ws3.example.com:8080;
}
server {
listen 80;
location /ws {
proxy_pass http://websocket_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400s;
}
}
# Example 2: AWS ALB with sticky sessions
# Target group stickiness configuration
stickiness:
enabled: true
type: app_cookie
cookie_name: AWSALB
cookie_duration_seconds: 86400
// Example 3: Stateless WebSocket with Redis adapter
const { Server } = require('socket.io');
const { createAdapter } = require('@socket.io/redis-adapter');
const { createClient } = require('redis');
const io = new Server();
const pubClient = createClient({ url: 'redis://redis:6379' });
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
io.listen(3000);
// Now any server can broadcast to any client
// Sticky sessions are still needed for initial connection
// But state is shared via Redis
Common Mistakes
- Relying solely on sticky sessions without a shared state layer
- Using source IP affinity when clients come from shared IPs (NAT)
- Setting cookie duration too short, causing frequent re-pinning
- Not configuring health checks that respect sticky sessions
- Forgetting that sticky sessions prevent even load distribution
Practice
- Configure Nginx with ip_hash for WebSocket Load Balancing.
- Set up a second WebSocket server and verify sticky sessions.
- Test what happens without sticky sessions when a server goes down.
- Implement a Redis-backed pub/sub for cross-server broadcasting.
- Challenge: Compare sticky session vs Redis pub/sub approaches for a chat application with 3 server instances.
FAQ
Mini Project
Deploy a Socket.IO chat application behind Nginx with ip_hash sticky sessions. Add a second server instance. Verify that a client always connects to the same server. Add Redis Adapter to share state across servers.
What's Next
Next, you will learn about WebSocket load balancing strategies for horizontal scaling.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro