A real-time web protocol is a communication standard that enables servers and browsers to exchange data continuously without repeated HTTP polling. Two transports dominate this category in production: WebSockets, which open a persistent TCP connection for full-duplex communication, and Server-Sent Events (SSE), which stream updates from server to client over a long-lived HTTP response. Both eliminate the latency and waste of HTTP long-polling, but they make very different demands on infrastructure, browsers, and the application code that drives them. Choosing between them is less about raw throughput and more about connection direction, load balancer behavior, and the operational cost of holding thousands of sockets open at once.
What Makes a Real-Time Web Protocol Different
A real-time web protocol replaces the request/response cadence of HTTP with a persistent connection that the server can write into whenever new data arrives. Classic HTTP polling forces the client to ask the server "anything new?" on a fixed interval. HTTP long-polling improves on that by holding each request open until data is available, then immediately reopening a new one. Both patterns waste header bytes and add round-trip latency, and HTTP long-polling still forces the client to drive every exchange.
Push-based transports invert that flow. The connection stays open, and the server emits frames or events as state changes. The two browser-native options for this push model are WebSockets and Server-Sent Events, and the choice between them depends on whether the client also needs to send data back through the same channel. For teams comparing event-delivery patterns more broadly, our guide on choosing between webhook and polling covers the server-to-server side of the same tradeoff.
- HTTP polling: client asks on a fixed interval; high overhead, predictable load, no push.
- HTTP long-polling: server holds the request open until data exists; lower latency than polling, still client-driven.
- Server-Sent Events: server streams events over a single long-lived HTTP response; unidirectional push.
- WebSocket connection: persistent TCP socket with bidirectional data transfer; full-duplex communication after an HTTP upgrade.
How WebSockets Work
A real-time web protocol such as WebSocket (WS) begins life as an ordinary HTTP request that asks the server to switch protocols. Once the server accepts the upgrade, the underlying TCP connection is reused as a framed, full-duplex channel. The behavior is defined by RFC 6455, with RFC 8441 describing how the same WebSocket handshake bootstraps over HTTP/2. The connection runs on the ws:// or wss:// scheme and supports both text and binary frames, which is why WebSockets remain the default transport for chat, gaming, and collaborative editing.
The handshake and frame lifecycle look like this in practice.
- The client opens a TCP connection and sends an HTTP
GETwithUpgrade: websocketand a randomly generatedSec-WebSocket-Keyheader. - The server responds with HTTP
101 Switching Protocolsand a derivedSec-WebSocket-Acceptvalue that confirms the handshake. - The same socket becomes a framed channel; either side can send text or binary frames at any time, enabling true bidirectional data transfer.
- Control frames carry
pingandpongheartbeats so intermediate proxies do not close the WS connection on idle timeout. - Either party sends a
closeframe with a status code, and the TCP socket is torn down.
The full-duplex communication model is what differentiates WebSockets from any HTTP-only transport. GitHub's engineering team documents how the platform uses a WebSocket connection to push code review updates, live presence indicators, and CI status into the browser in its post on real-time WebSockets. Frameworks such as Microsoft's ASP.NET Core SignalR wrap the WebSocket handshake with fallbacks to long-polling when corporate proxies block the upgrade.
How Server-Sent Events Work
A real-time web protocol can also flow in one direction, and that is the entire premise of Server-Sent Events. SSE is part of the HTML Living Standard and uses a single HTTP response with the text/event-stream content type. The server never closes the response; it keeps writing newline-delimited event records, and the browser parses them through the EventSource API. There is no protocol upgrade, no new scheme, and no separate transport library to ship.
EventSourceAPI: a one-line constructor in the browser,new EventSource('/stream'), that handles parsing and dispatching events.text/event-streamframing: each event is a block ofdata:,event:,id:, andretry:fields separated by a blank line.- Automatic reconnection: if the connection drops, the browser reopens it and replays the
Last-Event-IDheader so the server can resume the event stream from the last delivered record. - HTTP/2 multiplexing: SSE streams share a single HTTP/2 connection, which removes the six-per-origin cap that constrains SSE under HTTP/1.1.
- Plain HTTP transport: every proxy, CDN, and load balancer that understands HTTP also understands SSE, with no upgrade negotiation required.
The tradeoff is symmetry. SSE delivers server-to-client push only. If the browser needs to send data back, it does so through a separate fetch or XHR request. For dashboards, notifications, and log tails, that asymmetry is a feature: the application gets push semantics without paying for a full-duplex socket on every client.
WebSockets vs Server-Sent Events: Side-by-Side Comparison

A real-time web protocol comparison is most useful when it focuses on operational attributes rather than micro-benchmarks. The table below contrasts WebSockets and SSE across the dimensions that drive transport selection in production.
| Feature | WebSockets | SSE |
|---|---|---|
| Communication direction | Full-duplex communication | Server to client only |
| Underlying protocol | TCP after HTTP upgrade (RFC 6455) | HTTP/1.1 or HTTP/2 with text/event-stream |
| Browser support | All modern browsers; corporate proxies sometimes block the upgrade | All modern browsers except legacy Internet Explorer; broad browser support otherwise |
| Load balancer compatibility | Requires sticky sessions and WebSocket-aware load balancer | Works with any HTTP-aware load balancer or CDN |
| Reconnection behavior | Manual; application code must reconnect and resync state | Automatic reconnection through EventSource with Last-Event-ID replay |
| Binary support | Native binary and text frames | Text only; binary requires Base64 encoding |
| Connection overhead | Higher per-client memory; one persistent socket per session | Lower; standard HTTP response held open |
| Typical use cases | Chat, multiplayer games, collaborative editing, trading terminals | Live dashboards, notification streams, log tails, progress bars |
The pattern in that table is consistent: WebSockets buy bidirectional data transfer at the price of stateful infrastructure, while SSE trades direction for the operational simplicity of plain HTTP. Browser support is a near-tie for SSE and WebSockets on current evergreen browsers, so the deciding factor is usually the LB tier and the application's need for client-to-server messaging on the same channel.
Use Cases for Each Protocol
A real-time web protocol earns its keep when the application's data flow matches its connection model. The split between WebSockets and SSE tends to fall along the line of who initiates messages and how often.
WebSocket-suited scenarios share one trait: the client also produces a steady stream of events.
- Chat application backends, where each keystroke, typing indicator, and read receipt is a client-originated event that needs low-latency bidirectional data transfer.
- Multiplayer game servers, where input frames flow from clients to a tick loop on the server and authoritative state flows back many times per second.
- Collaborative editing tools, where CRDT or OT operations originate on every connected client and must be merged in near real time.
- Trading terminals, where order entry and market data share the same WebSocket connection for symmetry and predictable latency.
SSE-suited scenarios share the opposite trait: the server is the only meaningful publisher.
- Live dashboard updates, where the browser subscribes to an event stream of metrics and never sends anything richer than the initial GET.
- Financial data feed delivery, where price ticks fan out to read-only clients that place orders through a separate REST or RPC path.
- Notification streams, where in-app alerts, mentions, and status changes push to the browser without any client follow-up.
- Progress indicators for long-running server jobs, where the server reports completion percentage on a one-way channel until the job ends.
Many production systems mix both transports. Readers evaluating broader API patterns will find related ground in the pieces on GraphQL vs REST and the top API integration platforms for developers, which cover how request/response APIs sit alongside push transports in modern architectures.
Infrastructure and Scaling Considerations
A real-time web protocol does not exist in isolation; it sits behind edge proxys, CDNs, and connection-aware proxies that shape what you can run. WebSockets carry meaningfully higher operational complexity than SSE because they require the network path to remain transparent to the WebSocket handshake and to keep a TCP socket open for the life of the session.
- Reverse proxy policy. WebSocket traffic typically needs sticky sessions so that every frame from a given client lands on the same backend that holds its socket state. Most cloud L7 proxys support this, but it must be enabled explicitly and monitored for hot-spotting.
- Connection overhead per node. A persistent connection consumes file descriptors and kernel memory. Backends terminating tens of thousands of WS connections require tuned
ulimit, epoll-based event loops, and careful heap profiling. - Horizontal scaling. Stateful sockets do not migrate between nodes, so horizontal scaling depends on a pub/sub fan-out layer such as Redis or NATS that delivers messages to whichever node holds the recipient's socket.
- SSE on standard HTTP. Server-Sent Events ride existing HTTP infrastructure. Any HTTP/2-aware ingress proxy or reverse proxy handles them without sticky sessions, which makes horizontal scaling closer to a stateless web tier.
- Reconnection and resume. SSE provides automatic reconnection and
Last-Event-IDreplay in the browser. WebSockets push reconnection logic into application code, which has to detect drops, back off, and resynchronize state after each reconnect. - HTTP long-polling fallback. Where corporate proxies strip the WebSocket upgrade, libraries fall back to Long-polling, which restores connectivity at the cost of higher latency and more frequent connection overhead.
The deciding question is rarely raw performance. It is whether the operations team is prepared to run stateful socket fleets with sticky edge LB rules, or whether the application can be served by a unidirectional event stream that scales like any other HTTP endpoint.
Further reading
- RFC 6455: The WebSocket Protocol (IETF)
- RFC 8441: Bootstrapping WebSockets with HTTP/2 (IETF)
- HTML Living Standard: SSE (WHATWG)
- ASP.NET Core SignalR introduction (Microsoft Docs)
- How GitHub uses WebSockets for real-time (GitHub Engineering)
- Git Workflow Strategies Compared: Gitflow vs GitHub Flow vs GitLab Flow
- How To Implement API Rate Limiting and Throttling
- JWT vs OAuth 2.0 vs API Keys: Authentication Guide
The text/event-stream content type and the text/event-stream framing rules together define the SSE wire format.
Frequently Asked Questions
What are the main differences between WebSockets and Server-Sent Events?
WebSockets provide full-duplex communication over a persistent TCP connection, while SSE is a unidirectional channel that pushes server updates to the browser over standard HTTP. WebSockets suit interactive applications that send data in both directions; SSE suits applications that only need the server to push updates.
When should I use WebSockets over SSE?
Use WebSockets when the client must also send data continuously, such as in chat applications, multiplayer games, or collaborative editing tools. SSE is sufficient when only the server needs to broadcast updates, such as live sports scores, notification streams, or progress indicators.
Are there limitations to using Server-sent push?
SSE is limited to server-to-client data flow and carries a per-domain connection limit in HTTP/1.1 browsers, typically six concurrent connections. HTTP/2 removes that ceiling through multiplexing. SSE also lacks native binary frame support, so binary payloads require Base64 encoding.
Can WebSockets and SSE protocol be used in the same application?
Yes. A common pattern pairs SSE for high-volume server broadcasts, such as analytics dashboards, with a WebSocket channel for lower-frequency interactive commands. Each transport handles the direction it is optimized for, reducing the connection overhead of maintaining a full-duplex socket where unidirectional push suffices.
What are common issues when running WebSockets in production?
The most frequent production issues are connection drops behind proxies that enforce HTTP timeouts, L4 proxy misconfiguration that breaks sticky sessions, and memory pressure from holding thousands of open sockets. Heartbeat ping and pong frames plus a stateful edge node policy address the first two; horizontal scaling with a pub/sub broker such as Redis addresses the third.









