How to use Socket.IO rooms and namespaces
socket.join, socket.leave, io.to room emit, socket.to room emit (exclude sender), namespace with io.of, namespace connection event, namespace vs room comparison
Rooms: Subsets of Clients
A socket can join multiple rooms simultaneously. Joining and leaving is synchronous:
io.on('connection', (socket) => { socket.on('join:room', (roomId) => { socket.join(roomId); // Notify room members (excluding joiner) socket.to(roomId).emit('user:joined', { id: socket.id }); }); socket.on('room:message', ({ roomId, text }) => { // Broadcast to room including sender io.to(roomId).emit('room:message', { from: socket.id, text }); // Or excluding sender: // socket.to(roomId).emit(...) }); socket.on('leave:room', (roomId) => { socket.leave(roomId); socket.to(roomId).emit('user:left', { id: socket.id }); }); });
Namespaces: Separate Connection Contexts
Namespaces are like separate channels. Each has its own event handlers and rooms. Use them to separate concerns (e.g., /chat and /admin) without running multiple servers:
const chatNS = io.of('/chat'); const adminNS = io.of('/admin'); chatNS.on('connection', (socket) => { /* chat logic */ }); adminNS.on('connection', (socket) => { /* admin logic */ });
Client connects to a namespace with io('/chat'). A socket in one namespace cannot receive events from another.
