intermediate 2 min answer Multiple choice

A collaborative editor needs to push document changes to connected clients with minimal latency. Which transport should it use, and what does the choice imply for infrastructure?

websocketssserealtimestateful-tierfigmaarchitecture-selection
Pick one
Show the full answer Hide the answer

Why WebSockets

Collaborative editing is genuinely bidirectional and symmetric: every client is both a producer and a consumer of operations at similar rates. That rules out the one-directional options immediately.

  • Server-Sent Events are server-to-client only. Client operations would go over separate HTTP requests, adding a round trip and connection overhead to every keystroke-level operation, and losing ordering between the two channels.
  • Long polling has a round trip of overhead per message and holds a request open per client, which is the same resource cost as a persistent connection with worse latency.
  • HTTP/2 server push is for pushing resources the client will request, not for application messaging, and is deprecated in practice.

What the choice implies for infrastructure

A stateful tier, with all that follows. This is the part teams underestimate.

  • Connections pin to a process for their lifetime, so the connection tier cannot be load-balanced like a stateless one, and losing a process loses every session on it.
  • Deployments disconnect users unless draining is a protocol feature: the server tells clients to reconnect on a staggered schedule before it goes away. Without this, every deployment is a reconnect storm — a self-inflicted version of the platform's worst failure mode.
  • Layer 4 balancing rather than Layer 7, since per-request decisions are meaningless for an hours-long connection and a Layer 7 proxy becomes memory-bound holding state for it.
  • Capacity is measured in connections, not requests per second. CPU is the wrong autoscaling signal — a server holding many idle connections has low CPU while approaching memory and file-descriptor limits.
  • Reconnection must be cheap. A sequence number plus a bounded replay buffer, so reconnecting means "send me what I missed" rather than "refetch everything". This single property determines whether the system survives a mass disconnection.

The protocol design that matters more than the transport

  • Sequence numbers on every message, so gaps are detectable and resumption is possible.
  • Heartbeats in both directions, because a TCP connection can be dead for minutes without either side noticing — a half-open connection is the characteristic silent failure of long-lived connections.
  • Server-enforced reconnect backoff, since client politeness is ignored by old and third-party clients.
  • A message-size limit and per-connection rate limit, because a persistent connection is an unbounded input channel.

The honest caveat

If the requirement were only server-to-client notifications — a dashboard, a live feed, a progress indicator — Server-Sent Events would be the better answer: simpler, works over ordinary HTTP, reconnects and resumes automatically, and traverses proxies without special handling. WebSockets are justified by symmetry, not by "real-time", and reaching for them when the traffic is one-directional buys operational complexity for nothing.