| name | websocket-patterns |
| description | Production-ready patterns for real-time bidirectional communication based on RFC 6455 and Socket.io best practices. |
WebSocket Patterns
Production-ready patterns for real-time bidirectional communication. Based on RFC 6455 (WebSocket Protocol), Socket.io v4 docs, and MDN WebSocket API.
Sources: RFC 6455, Socket.io Documentation, MDN Web Docs
Connection Lifecycle (RFC 6455)
States: CONNECTING (0), OPEN (1), CLOSING (2), CLOSED (3)
Server (Socket.io)
const io = new Server(server, {
pingTimeout: 60000,
pingInterval: 25000,
cors: { origin: process.env.CLIENT_URL }
});
io.on('connection', (socket) => {
socket.on('disconnect', (reason) => {
});
});
Client Reconnection
const socket = io('http://localhost:3000', {
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
reconnectionAttempts: 5
});
socket.on('connect', () => {
});
Authentication (Pre-Connection)
io.use((socket, next) => {
const token = socket.handshake.auth.token;
try {
socket.data.user = jwt.verify(token, SECRET);
next();
} catch (err) {
next(new Error('Auth failed'));
}
});
const socket = io({ auth: { token: getToken() } });
Message Patterns
Rooms (Pub/Sub)
socket.join(roomId);
io.to(roomId).emit('event', data);
socket.to(roomId).emit('event', data);
Acknowledgements (Request-Response)
socket.on('send-msg', (msg, callback) => {
if (!msg.text) return callback({ error: 'Required' });
callback({ success: true, id: saved.id });
});
socket.emit('send-msg', msg, (response) => {
if (response.error) handleError();
});
Broadcast
io.emit('event', data);
socket.broadcast.emit('event', data);
Heartbeat/Ping-Pong (RFC 6455 ยง5.5.2-5.5.3)
Socket.io handles automatically via pingInterval/pingTimeout. Native WebSocket:
const ws = new WebSocket('ws://localhost');
ws.addEventListener('open', () => {
setInterval(() => ws.send('ping'), 30000);
});
Error Handling
Connection Errors
socket.on('connect_error', (err) => {
if (err.message === 'Auth failed') redirectLogin();
});
socket.on('error', (err) => {
logger.error({ socketId: socket.id, err });
});
Message Validation
socket.on('chat-msg', (msg) => {
const result = schema.safeParse(msg);
if (!result.success) return socket.emit('error', 'Invalid');
});
Scalability (Multi-Server)
Redis Adapter (Socket.io)
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';
const pubClient = createClient({ url: 'redis://localhost:6379' });
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
Sticky Sessions (Required)
Use IP-based routing or session ID cookies to route client to same server instance.
Resources