Real-Time Backend

Socket.IO Fundamentals

Цели урока

  • Understand the Socket.IO handshake and upgrade mechanism
  • Distinguish Namespace from Room and choose the right isolation level
  • Use acknowledgements for reliable event delivery
  • Understand the polling fallback strategy and its trade-offs

In 2016, WhatsApp served 1 billion users with a team of 50 engineers. The foundation was a protocol with reconnection, acknowledgements, and multiplexing. Socket.IO delivers all of that out of the box in five lines of code.

  • **Slack** - Namespace per workspace, Rooms per channel, Ack for delivery guarantees
  • **Figma** - real-time collaboration: each document is a separate Socket.IO Room
  • **Trello** - live updates with polling fallback for enterprise clients behind proxies

Socket.IO: handshake and upgrade

HTTP is request-response: a server cannot push data without being asked first. **Socket.IO** addresses this in three steps: it starts with HTTP long-polling (works everywhere), attempts a **WebSocket upgrade**, and if the upgrade succeeds - stays on WebSocket permanently.

The first request is the **handshake**: the client receives a `sid` (session identifier), `pingInterval`, `pingTimeout`, and a list of available transports. Polling begins immediately while the client simultaneously attempts the WebSocket upgrade.

Socket.IO is **not** just WebSocket. On top of it (or polling) sits a custom protocol: automatic ping/pong, reconnection on disconnect, acknowledgements, and namespace multiplexing.

Socket.IO starts with long-polling rather than WebSocket directly. The main reason:

Rooms and Namespaces

A messaging app has thousands of chats, but each user should only receive messages from their own. Socket.IO provides two grouping levels: **Namespace** (separate application domains on one server) and **Room** (groups of sockets within a namespace).

A **Namespace** is a separate endpoint: `/chat`, `/admin`, `/notifications`. Different namespaces are isolated - events from `/chat` do not reach `/admin`. A **Room** is a dynamic group within a namespace. A socket can belong to multiple rooms simultaneously, and every socket automatically joins a personal room named after its `socket.id`.

When should a separate Namespace be used instead of a Room?

Acknowledgements and reliability

WebSocket is fire-and-forget: a packet is sent, and there is no built-in confirmation that it arrived. For a chat application this is a problem - a user sees a "sent" checkmark, but the message may have been lost. **Acknowledgements** (ack) solve this: the sender waits for an explicit confirmation from the receiver before treating the event as delivered.

An ack is not an automatic delivery guarantee. It is an **application-layer confirmation**: the server received the event, processed it, and returned a result. If the connection breaks before the ack arrives, Socket.IO will reconnect, but the event will not be re-sent automatically. That responsibility lies with the application.

For true at-least-once delivery, idempotent logic is required: the client stores each event with a unique `clientEventId` and retransmits on reconnect; the server deduplicates by that id.

A Socket.IO acknowledgement guarantees that a message:

Fallback: polling transport

Corporate networks often block WebSocket: proxies do not understand `Upgrade: websocket` and terminate the connection. Socket.IO automatically falls back to **HTTP long-polling** - the browser sends a GET request, the server holds it open until an event arrives (or a timeout), and then the client immediately issues the next request.

When WebSocket is unavailable due to a proxy and low latency is critical, consider **Server-Sent Events** for server-to-client direction and HTTP POST for client-to-server. SSE passes through most proxies and is faster than polling.

Socket.IO is configured with `transports: ['polling', 'websocket']`. WebSocket is blocked by a corporate proxy. The outcome:

Socket.IO Fundamentals

  • Handshake issues a sid, starts with polling, then upgrades to WebSocket
  • Namespace: middleware and logic isolation for separate application endpoints
  • Room: dynamic groups within a namespace for targeted broadcast
  • Acknowledgements: callback confirms application-level processing
  • Polling fallback is transparent to the application; the API does not change

Related Topics

Socket.IO builds on WebSocket and addresses problems found throughout the real-time stack.

  • WebSocket Protocol — Socket.IO uses WebSocket as its primary transport with a custom protocol on top
  • Server-Sent Events — An alternative to the polling transport for the server-to-client direction
  • Socket.IO Advanced — Middleware, binary data, volatile events and Redis Adapter for scaling

Вопросы для размышления

  • When does it make sense to abandon Socket.IO in favor of the native WebSocket API?
  • How can at-least-once delivery be built on top of acknowledgements under unstable connections?
  • In what scenarios is a Namespace preferable to running separate Socket.IO servers?

Связанные уроки

  • rt-05 — Socket.IO runs on WebSocket by default; understanding the transport is required
  • rt-08 — Socket.IO serialization choices (JSON + binary) become clear after the serialization lesson
  • rt-10 — Socket.IO advanced features (rooms, namespaces, adapters) build directly on the basics
  • rt-06 — Socket.IO is one of the 'approaches' compared in rt-06; seeing the comparison motivates the library choice
  • net-36-websocket
Socket.IO Fundamentals

0

1

Sign In