Server Design
So far this course has lived mostly on the client side — opening a socket, sending frames, watching messages arrive. This module flips the camera around. A WebSocket server is a long-running process that holds many open connections at once and decides who hears what. That is a genuinely different mental model from an HTTP handler, and getting it right is the difference between a demo and a system.
What a WebSocket server actually does
Section titled “What a WebSocket server actually does”An HTTP server thinks in terms of one request, one response, then forget you. A WebSocket server cannot afford to forget you — you are still on the line. Strip the job down and it is really four responsibilities:
- Accept upgrades. A connection begins life as an ordinary HTTP request carrying an
Upgrade: websocketheader. The server validates it and switches the socket over to the WebSocket protocol. From that point on it is a persistent pipe, not a request. - Track connections. Every accepted socket has to be remembered. The server keeps a live set of who is connected so it can find them again later — to push an update, to count them, or to clean up when they leave.
- Route messages. When a frame arrives, the server reads it and decides what it means: a chat line for one room, a subscription request, a ping, a command. Routing turns raw bytes into application behaviour.
- Broadcast. The headline trick. Because the server holds every open socket, it can deliver a single event to many clients at once — the moment it happens, with nobody having asked.
Notice that three of those four are things an ordinary HTTP server never has to do. Tracking, routing across a persistent connection, and fan-out only make sense once connections stay open.
One server, many clients
Section titled “One server, many clients”A useful way to picture a WebSocket server is as a hub holding one wire to each client. A message from any single client can come in, be processed, and then go back out to one client, a subset, or everyone:
flowchart TB
subgraph clients["Connected clients"]
A["client A"]
B["client B"]
C["client C"]
D["client D"]
end
S["WebSocket server<br/>(tracks every open socket)"]
A <--> S
B <--> S
C <--> S
D <--> S
A -. "sends one message" .-> S
S == "broadcast to all" ==> B
S == "broadcast to all" ==> C
S == "broadcast to all" ==> D The double-headed lines are the persistent connections; the thick lines are a single inbound message being fanned out to everyone else. Hold onto that shape — almost everything in this module is a refinement of it.
What this module covers
Section titled “What this module covers”This module — Server Design — builds the server-side half of your WebSocket knowledge, one layer at a time:
- Server Design (you are here) — the four jobs of a server and a first live
wsserver. - A WebSocket server — the
wslibrary:WebSocketServer, theconnectionevent,ws.on('message'), andws.send. - Connection state — attaching per-socket data (user id, subscriptions) and cleaning it up on close.
- Rooms and broadcast — grouping clients into channels and fanning a message out to a room versus everyone.
- Backpressure — what happens when a slow client cannot keep up, and how to protect the server’s memory.
A first live server
Section titled “A first live server”The demos in this module are real Node servers built on the ws library — the most widely used WebSocket library for Node. Open any of them in StackBlitz to run a genuine WebSocketServer, then npm run client in a second terminal to connect.
Throughout this module, the code you see is the body of the connection handler — it runs once per connected client, with three identifiers already in scope: ws (this client’s socket), wss (the server, for broadcast), and req (the upgrade request). The example below greets each new client, echoes whatever they send, and logs when they leave.
Needs the Node.js runtime — open in StackBlitz to run.
When you connect the client, the server sends a greeting immediately, then echoes your message back with an echo: prefix. That ws.send on connect — before the client says anything — is the part HTTP can never do: the server speaks first. Everything else in this module builds on holding that connection open and deciding what to send across it.