Real-Time Backend

Socket.IO Advanced

Цели урока

  • Implement JWT authentication via Socket.IO middleware
  • Transfer binary data without base64 overhead
  • Distinguish volatile from regular events and apply each correctly
  • Configure the Redis Adapter for multi-instance scaling

In 2019 Figma was serving millions of collaborative editing sessions. The core challenge: cursor positions of all participants had to be broadcast in real time, but with 20 users in a document that is 20 * 30 = 600 events per second. The solution was volatile events for cursors and regular events for document changes. The Redis Adapter enabled horizontal scaling.

  • **Figma** - volatile events for participant cursors, regular events for document operations
  • **Socket.IO on Kubernetes** - Redis Adapter is standard when deploying across multiple pods
  • **Real-time games** - binary transfer for game state, volatile for player positions

Socket.IO Middleware and authentication

HTTP middleware stops an unauthenticated request at the gate. In Socket.IO the same pattern works through **middleware** - a function called for every new connection before the socket receives its first event. This is the right place to verify a JWT, session, or API key and reject the connection.

Middleware can be chained: the first checks the JWT, the second enforces rate limits, the third logs the connection. Each receives the same `socket` object and `next`. **Important**: middleware runs only at connection time. Authorizing individual events requires additional checks inside event handlers.

Namespace middleware runs only for sockets in that namespace. This makes it possible to have separate authorization for `/public` and `/admin` without duplicating logic.

Socket.IO middleware is called:

Binary data in Socket.IO

Sending an image through Socket.IO as base64 turns 1 MB of binary data into 1.37 MB of text. Socket.IO supports native transmission of **binary data** via `ArrayBuffer` and `Buffer` - no encoding, minimal overhead. Socket.IO automatically detects binary payloads and uses a dedicated binary packet type.

Socket.IO uses a special format for binary packets: an object with `_placeholder: true` for each binary buffer, followed by separate binary frames. This allows mixing JSON metadata and binary data within a single event.

Why is sending files through Socket.IO as a Buffer better than as a base64 string?

Volatile events and buffering

Cursor coordinates in a collaborative editor are emitted 30 times per second. If a client is temporarily unavailable (background tab, poor connection), buffering 300 stale positions is pointless - only the latest one matters. **Volatile events** handle this: if the client is not ready to receive an event at that moment, it is simply dropped.

Which event should be sent as volatile?

Socket.IO Adapters: Redis Adapter

A single Socket.IO server handles up to ~10,000 connections. With horizontal scaling (three instances), a problem emerges: socket A is on instance 1, socket B is on instance 2. Calling `io.to('room-42').emit(...)` on instance 1 reaches only the sockets connected to that instance. An **Adapter** solves this by making broadcast cross-process.

The Redis Adapter adds ~1-2 ms of latency per broadcast (round-trip through Redis). For most real-time applications this is imperceptible. When that matters, consider the Cluster Adapter for single-host deployments or sticky sessions with namespace sharding.

Without the Redis Adapter in a horizontally scaled Socket.IO deployment (3 instances), `io.to('room').emit()` will deliver the event to:

Socket.IO Advanced

  • Middleware authenticates at connect time; result is stored on the socket object
  • Buffer/ArrayBuffer is transmitted natively without base64, zero overhead
  • Volatile events are dropped when the client is not ready - for high-frequency data
  • Redis Adapter synchronizes broadcast across instances via Pub/Sub
  • Without an adapter each instance sees only its own sockets

Related Topics

The advanced Socket.IO features address security and scaling requirements of production systems.

  • Socket.IO Fundamentals — Handshake, Rooms, Namespaces, and Acknowledgements are the foundation for advanced features
  • Redis Pub/Sub — The Redis Adapter uses Pub/Sub as the transport for cross-process broadcast
  • Scaling WebSocket Servers — Horizontal Socket.IO scaling via adapters and sticky sessions

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

  • How can per-event authorization be implemented beyond the connection-level middleware?
  • In what scenarios is the Redis Streams Adapter preferable to the Redis Pub/Sub Adapter?
  • How do volatile events affect UX in collaborative applications under poor network conditions?

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

  • rt-09 — Advanced features assume mastery of basic Socket.IO API from rt-09
  • rt-11 — uWebSockets.js vs Socket.IO advanced represents the performance vs developer-experience tradeoff
  • rt-08 — Binary protocol support in Socket.IO advanced connects back to the serialization lesson
  • rt-05 — Knowing WebSocket deeply helps when Socket.IO advanced features (like transport switching) behave unexpectedly
  • net-36-websocket
Socket.IO Advanced

0

1

Sign In