Introduction
In a real-time application, you rarely work with WebSockets in isolation. Clients need targeted messages (sent to one specific socket) as well as broadcast events (fired to every connected client). On top of that, most real products still expose a REST API — for example, when a user submits a form over HTTP, you want that change to appear instantly in every open WebSocket session. This lesson covers exactly that: how to send and broadcast events from a Node.js server, and how to bridge a REST endpoint with your WebSocket layer so both surfaces stay in sync.
Sending messages to one client vs broadcasting
Every connected socket has a unique id assigned by the server. You can use that id to send a private message:
If you want every connected client to receive the same payload, you broadcast on the root namespace — no target argument needed:
There is also `socket.broadcast.emit`, which sends to everyone except the socket that triggered the event. This is useful in chat rooms where you do not want to echo the message back to the sender.
Bridging a REST endpoint with WebSocket events
The typical pattern is: REST handler does its job (write to database, validate input, etc.), then asks the WebSocket layer to push an update. Here is a minimal example using Express alongside Socket.IO:
The HTTP client gets the created order in its REST response, and every browser tab connected over WebSocket receives the `order:new` event at the same time. One write, two surfaces.
Targeting specific rooms
When you need finer control than "everyone" or "one socket", use rooms. A room is just a named channel that sockets join or leave:
`socket.to("orders")` reaches every socket in that room except the sender. `io.to("orders").emit(...)` reaches everyone in the room including the sender. Rooms are the standard way to implement per-user, per-team, or per-topic feeds without writing custom routing logic.
Common mistakes
Calling `io.emit` inside the REST handler is fine, but do not forget that the REST response and the WebSocket emit are independent — if the WebSocket layer crashes, the HTTP request still returns success. For critical flows, wrap the broadcast in a try/catch and log failures. Another frequent error is mixing `socket.emit` (sends to the current socket only) with `io.emit` (sends globally) and assuming they behave the same. Pick the one that matches your intent. Finally, never trust the `socket.id` sent from the client — always look it up server-side from your authenticated session before sending private data.
Summary
You now have three delivery modes: `socket.emit` for the current client, `io.emit` for global broadcast, and rooms for targeted groups. Pairing a REST handler with `io.emit` (or `io.to(room).emit`) is the standard bridge pattern that keeps HTTP and WebSocket surfaces consistent. Keep the broadcast inside the REST handler after the main business logic, handle WebSocket failures gracefully, and always verify identities server-side before sending private payloads.
Lesson Checkpoint
Review what you learned and get feedback on your work.