Broadcasting is what makes WebSocket genuinely powerful. One message from the server can instantly reach thousands of connected clients. There are three distinct sending patterns every real-time app uses.


The 3 Broadcasting Patterns

Pattern Who receives? Real-world example
Broadcast Every connected client Live score update, breaking news
Unicast One specific client Private message, personal notification
Exclude Everyone except the sender Chat: show your message to others, not yourself

Pattern 1 — Broadcast to ALL Clients

// server.js
const { WebSocket } = require('ws');

wss.on('connection', (ws) => {
  ws.on('message', (data) => {
    const msg = JSON.parse(data);

    // Send to every connected client (including sender)
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify({
          type: 'broadcast',
          text: msg.text,
          timestamp: Date.now(),
        }));
      }
    });
  });
});

Pattern 2 — Exclude Sender

Most common in chat apps — broadcast to everyone except the person who sent the message:

wss.on('connection', (ws) => {
  ws.on('message', (data) => {
    const msg = JSON.parse(data);

    // Send to all EXCEPT the sender
    wss.clients.forEach((client) => {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify(msg));
      }
    });
  });
});

Pattern 3 — Unicast (Send to One Specific Client)

You must track clients by ID yourself:

const { v4: uuidv4 } = require('uuid'); // npm install uuid
const clientMap = new Map();             // clientId → ws socket

wss.on('connection', (ws) => {
  // Assign unique ID
  const clientId = uuidv4();
  ws.clientId = clientId;
  clientMap.set(clientId, ws);

  // Send the client their own ID
  ws.send(JSON.stringify({ type: 'identity', id: clientId }));

  ws.on('message', (data) => {
    const msg = JSON.parse(data);

    if (msg.type === 'private') {
      // Send to one target
      const target = clientMap.get(msg.targetId);
      if (target?.readyState === WebSocket.OPEN) {
        target.send(JSON.stringify({
          type: 'private',
          from: clientId,
          text: msg.text,
        }));
      }
    }
  });

  ws.on('close', () => {
    clientMap.delete(clientId);
    console.log(`${clientId} left. ${clientMap.size} remaining.`);
  });
});

Client-Side — Receiving Broadcasts

// client.js
const ws = new WebSocket('ws://localhost:8080');

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);

  switch (data.type) {
    case 'identity':
      console.log('My ID:', data.id);
      break;
    case 'broadcast':
      console.log('Global message:', data.text);
      break;
    case 'private':
      console.log(`Private from ${data.from}:`, data.text);
      break;
  }
};

// Send a private message
ws.send(JSON.stringify({
  type: 'private',
  targetId: 'some-client-uuid',
  text: 'Hey, just you!',
}));

Performance Note