WebSockets provide full-duplex communication over a single TCP connection — ideal for chat, live feeds, and collaborative apps.

WebSocket vs HTTP

HTTP WebSocket
Request-response Persistent connection
Client initiates Both sides can send anytime
Headers on every request Low overhead after handshake
Polling for updates Push updates instantly

Native WebSocket (ws package)

  npm install ws
  
  import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 8080 });

wss.on('connection', (ws) => {
    console.log('Client connected');

    ws.send(JSON.stringify({ type: 'welcome', message: 'Hello!' }));

    ws.on('message', (data) => {
        const msg = JSON.parse(data);
        // Broadcast to all clients
        wss.clients.forEach(client => {
            if (client.readyState === 1) { // OPEN
                client.send(JSON.stringify(msg));
            }
        });
    });

    ws.on('close', () => console.log('Client disconnected'));
});
  

Handles reconnection, rooms, and fallbacks automatically:

  npm install socket.io
  

Server:

  import express from 'express';
import { createServer } from 'http';
import { Server } from 'socket.io';

const app = express();
const server = createServer(app);
const io = new Server(server, {
    cors: { origin: 'http://localhost:5173' }
});

io.on('connection', (socket) => {
    console.log('User connected:', socket.id);

    socket.on('join-room', (roomId) => {
        socket.join(roomId);
        socket.to(roomId).emit('user-joined', socket.id);
    });

    socket.on('chat-message', ({ roomId, text, user }) => {
        io.to(roomId).emit('chat-message', { text, user, time: Date.now() });
    });

    socket.on('disconnect', () => {
        console.log('User disconnected:', socket.id);
    });
});

server.listen(3000);
  

Client (browser):

  import { io } from 'socket.io-client';

const socket = io('http://localhost:3000');

socket.emit('join-room', 'general');

socket.on('chat-message', (msg) => {
    console.log(`${msg.user}: ${msg.text}`);
});

function sendMessage(text) {
    socket.emit('chat-message', { roomId: 'general', text, user: 'Alice' });
}
  

Rooms and Namespaces

  // Namespace for admin
const adminIo = io.of('/admin');
adminIo.on('connection', (socket) => {
    // Admin-only events
});

// Rooms within a namespace
socket.join('room-123');
io.to('room-123').emit('update', data);
  

Scaling with Redis

For multiple server instances:

  npm install @socket.io/redis-adapter redis
  
  import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';

const pubClient = createClient({ url: 'redis://localhost:6379' });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
io.adapter(createAdapter(pubClient, subClient));
  

Use Cases

  • Chat applications
  • Live notifications
  • Collaborative editing
  • Real-time dashboards
  • Online gaming

See the Real-Time Chat project for a full implementation guide.