Episode 3 — NodeJS MongoDB Backend Architecture / 3.15 — Realtime Communication WebSockets

3.15 — Quick Revision: Realtime Communication & WebSockets

Rapid-fire revision notes for WebSocket concepts, Socket.io API, rooms, namespaces, and middleware.


<< Back to README


WebSocket Protocol

  • Full-duplex communication over a single TCP connection
  • Starts with HTTP Upgrade handshake (101 Switching Protocols)
  • Protocols: ws:// (unencrypted) and wss:// (TLS encrypted -- always use in production)
  • Lifecycle: Open -> Message (many) -> Close
  • Frame overhead: ~2-6 bytes (vs ~800+ bytes for HTTP headers)
  • Use cases: chat, notifications, gaming, collaborative editing, live data

Polling vs SSE vs WebSocket

Short PollingLong PollingSSEWebSocket
DirectionClient -> ServerClient -> ServerServer -> ClientBidirectional
LatencyHighMediumLowVery Low
BandwidthWastefulMediumEfficientMost Efficient
Best forSimple dashboardsModerate updatesServer push onlyTwo-way real-time

Socket.io Basics

// Server setup
const server = http.createServer(app);
const io = new Server(server, { cors: { origin: '*' } });
// Use server.listen(), NOT app.listen()

// Connection
io.on('connection', (socket) => {
  socket.emit('event', data);              // to this client
  io.emit('event', data);                  // to ALL clients
  socket.broadcast.emit('event', data);    // to all EXCEPT sender
  socket.on('disconnect', (reason) => {}); // cleanup
});

// Client
const socket = io('http://localhost:3000');
socket.on('connect', () => {});
socket.emit('event', data);
socket.on('event', (data) => {});

Rooms

socket.join('room');                         // join
socket.leave('room');                        // leave
io.to('room').emit('event', data);          // all in room
socket.to('room').emit('event', data);      // room except sender
const sockets = await io.in('room').fetchSockets(); // get members
// Sockets auto-leave all rooms on disconnect

Namespaces

const chatNs = io.of('/chat');              // create namespace
chatNs.on('connection', (socket) => {});    // handle connections
// Client: io('http://localhost:3000/chat')
// Namespaces = separate features; Rooms = groups within a feature

Middleware

io.use((socket, next) => {
  const token = socket.handshake.auth.token;  // get token
  // verify -> socket.user = userData -> next()
  // reject -> next(new Error('message'))
});
// Per-namespace: chatNs.use(middleware)
// Client error: socket.on('connect_error', (err) => {})

Key Gotchas

  • Socket.io is NOT interoperable with raw WebSocket
  • app.listen() creates a separate server -- use server.listen() instead
  • disconnecting event still has socket.rooms; disconnect does not
  • React Strict Mode causes double mount -- clean up listeners in useEffect return
  • Configure CORS when frontend/backend are on different origins
  • Rooms are server-side only -- clients do not know which rooms they are in

<< Back to README