Side by side
| Dimension | WebSockets | Server-Sent Events |
|---|---|---|
| Data direction | Bidirectional over one connection | Server-to-client stream; separate requests for writes |
| Message format | Text or binary messages | UTF-8 text events |
| Browser API | WebSocket | EventSource |
| Reconnect behavior | Application implements reconnect and resume | EventSource reconnects and can send Last-Event-ID |
| Infrastructure | Needs WebSocket-aware proxy and load balancer configuration | HTTP streaming; disable unwanted response buffering |
| Connection limits | Persistent connection; capacity depends on deployment | Low per-origin browser limits on HTTP/1.1; HTTP/2 multiplexes streams |
| Delivery guarantees | No built-in durable replay or processing acknowledgment | Event IDs help resume; durable replay remains application work |
| Slow clients | Bound queues; define drop or disconnect policy | Bound queues; define drop or disconnect policy |
The differences that matter
The main decision is communication direction, not whether the feature is called real time. A live order tracker can use SSE for updates and POST requests for customer actions. A collaborative editor with frequent edits and cursor updates in both directions usually fits WebSockets better.
WebSockets carry text and binary messages, while SSE carries UTF-8 text in an HTTP response with Content-Type: text/event-stream. SSE works well for JSON events. Binary payloads require text encoding with SSE, so WebSockets are a better fit when binary messaging is part of the requirement.
Native EventSource automatically reconnects and, after receiving an event ID, can include Last-Event-ID when reconnecting. The server still needs retained events, cursor validation, and a policy for expired cursors. WebSockets require application-level reconnect and resume logic; neither option prevents duplicates across reconnects.
Both designs hold long-lived connections and need connection-aware capacity planning, fan-out, heartbeats, and graceful draining. SSE requires checking proxy buffering and streaming timeouts; WebSockets require compatible connection handling throughout the proxy path. HTTP/1.1 browser connection limits can make multiple SSE streams across tabs problematic, while HTTP/2 reduces that constraint through multiplexing.
Neither browser API provides automatic application-level flow control for incoming events. Bound per-client queues and decide whether to coalesce updates, drop replaceable events, or disconnect slow consumers. Latest-price displays can often coalesce updates; chat history generally needs durable recovery instead.
Choose WebSockets when
- Clients and servers exchange frequent messages, such as chat messages, typing indicators, receipts, and presence updates.
- Collaborative editing requires frequent upstream edits and downstream broadcasts on one session.
- The application needs binary messages without text encoding.
- Subscription changes and other client control messages are frequent enough that a bidirectional connection simplifies the protocol.
Choose Server-Sent Events when
- The browser mostly receives updates, while user actions already fit ordinary HTTP endpoints.
- You are streaming notifications, job progress, order status, or live comments to viewers.
- You want native browser reconnect behavior and an event-ID mechanism, while implementing retention and replay on the server.
- Your deployment supports reliable HTTP streaming, and text events meet the payload requirements.
A worked example
Live comments with occasional writes
Suppose a live event has 100,000 connected viewers. Each viewer receives two comment updates per second, averaging 300 bytes each. That is about 60 MB/s of application payload before protocol overhead, replication, and retries. Most viewers never post, so SSE plus an HTTP POST endpoint is a reasonable choice. Persist accepted comments, assign stream sequence numbers, and let reconnecting viewers request a retained range. If a viewer falls beyond retention, return a recent snapshot rather than buffering indefinitely. WebSockets would also work, but would not reduce the fan-out requirement. If the product adds frequent bidirectional interactions, reconsider WebSockets based on that traffic.
In the interview
- State the traffic shape first: concurrent clients, updates per second, payload size, and upstream message frequency. Do not justify WebSockets only by saying the product needs low latency.
- Separate the live transport from the durable data path. Explain when an event is persisted, how it reaches connection servers, and how reconnecting clients recover missed events.
- Describe connection ownership and fan-out: a load balancer places connections, gateways maintain local subscriptions, and a routing or pub-sub layer delivers relevant events. Existing connections stay on one gateway, but reconnects should not require the same gateway.
- Expect probes about slow consumers and reconnect storms. Specify bounded queues, heartbeats, connection draining, and a retry strategy with jitter; do not assume native EventSource reconnect alone provides fleet-wide storm control.
- Cover browser authentication constraints. Native WebSocket and EventSource constructors do not accept arbitrary authorization headers; discuss secure cookies or another carefully designed mechanism, validate origins, and explain session expiration and revocation.
Common mistakes
- Claiming SSE cannot support an interactive application. It cannot send upstream events on the SSE stream, but separate HTTP requests can handle client actions.
- Treating SSE auto-reconnect or an open WebSocket as a guarantee that no events are lost. Recovery needs retained state, cursors, and deduplication where appropriate.
- Assuming SSE is automatically proxy-safe or WebSockets are inherently faster. Buffering, timeouts, batching, and network conditions affect both designs.
- Ignoring connection count, multiple browser tabs, and slow-client queues while sizing only request throughput.
Where it comes up
Interview questions where choosing between WebSockets and Server-Sent Events comes up.
- Design a chat app like WhatsAppFrequent bidirectional messages make WebSockets a natural choice, while reconnect recovery and offline delivery remain separate design problems.
- Design Google DocsEdits and cursor updates require choosing a live transport without confusing it with convergence or durable replay.
- Design Facebook live commentsSSE plus HTTP writes is a strong option for mostly passive viewers, with hot-stream fan-out and bounded delivery as the main scaling concerns.
- Design a real-time stock price feedThe transport choice must account for subscription changes, latest-value coalescing, and reconnect behavior across regions.
- Design a notification systemBrowser notifications can use SSE or WebSockets, but durable notification processing must remain independent of the live connection.
- Design an ETA and live location sharing serviceViewer-facing location updates can use SSE even when location ingestion uses a separate upstream channel.
Questions people ask
Is SSE better than WebSockets?
SSE is often simpler for server-to-browser text updates when client writes already use HTTP. WebSockets are a better fit for frequent bidirectional messaging or binary messages. Choose based on traffic direction and operational requirements, not a blanket performance ranking.
Does SSE automatically recover missed events?
Native EventSource reconnects automatically and can send the last received event ID. The server must retain events and implement replay from that ID. If the cursor is too old, the application needs a snapshot or another resynchronization path.
Do WebSockets scale better than SSE?
Neither has an inherent scaling advantage that settles the design. Both require capacity for long-lived connections, outbound bandwidth, subscriptions, and slow consumers. Browser connection limits, HTTP version, proxy behavior, and upstream traffic can make one a better fit for a particular deployment.