Practical SSE vs WebSocket comparison for frontend interviews: protocol behavior, reconnect strategy, infrastructure trade-offs, and architecture decisions for AI streaming, notifications, chat, and collaboration.
SSE vs WebSocket in JavaScript: which real-time transport should you choose?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Definition (above the fold)
Use SSE (Server-Sent Events) when updates are mostly server -> client and you want a simple HTTP-based stream with automatic reconnect. Use WebSocket when you need true bidirectional, low-latency messaging (client and server both sending frequently). The choice should follow interaction shape, not preference.
Decision heuristic
Ask two questions first: (1) Does the client need to push frequent live events upstream? (2) Do you need strict duplex semantics like collaborative cursors or multiplayer state sync? If both answers are no, SSE is often cheaper and simpler to operate.
Dimension | SSE | WebSocket |
|---|---|---|
Directionality | Server -> client only | Full duplex (client <-> server) |
Transport | Standard HTTP response stream | Upgrade handshake to WebSocket protocol |
Reconnect behavior | Built-in auto-reconnect in EventSource | Custom reconnect/backoff logic required |
Infra compatibility | Works well with HTTP tooling/proxies/CDNs | May need extra gateway/proxy config |
Best-fit workloads | AI token streams, notifications, logs | Chat input streams, collaboration, games |
Operational complexity | Lower for one-way streaming | Higher but more flexible |
Runnable example #1: SSE client with typed events
const stream = new EventSource('/api/events?channel=orders');
stream.addEventListener('message', (event) => {
const payload = JSON.parse(event.data);
renderUpdate(payload);
});
stream.addEventListener('error', () => {
showBanner('Reconnecting to live updates...');
});
function stopStreaming() {
stream.close();
}
SSE keeps the client code compact for one-way streams and handles reconnect internally, which is ideal for feed-like updates.
Runnable example #2: WebSocket with heartbeat + reconnect
let socket;
let retries = 0;
function connect() {
socket = new WebSocket('wss://example.com/realtime');
socket.onopen = () => {
retries = 0;
socket.send(JSON.stringify({ type: 'subscribe', roomId: 'chat-42' }));
};
socket.onmessage = (event) => {
const msg = JSON.parse(event.data);
applyRealtimePatch(msg);
};
socket.onclose = () => {
const delay = Math.min(1000 * 2 ** retries++, 15000);
setTimeout(connect, delay);
};
}
connect();
Scenario | Recommended transport | Reason |
|---|---|---|
AI text streaming to user | SSE | One-way token delivery with simple reconnect |
Live metrics dashboard | SSE | Server pushes events, client rarely sends state |
Collaborative whiteboard | WebSocket | Many low-latency client edits upstream |
Multiplayer game state | WebSocket | Bidirectional high-frequency updates |
Order status notifications | SSE | Simple fan-out over existing HTTP infrastructure |
Common pitfalls
- Choosing WebSocket by default when one-way streaming would be simpler with SSE.
- Ignoring reconnection/backoff and duplicate message handling in WebSocket clients.
- Skipping auth token refresh strategy for long-lived connections.
Interview follow-ups
Q1: How do you handle message ordering on reconnect? A: Use monotonic event IDs and replay from last acknowledged ID.
Q2: What about backpressure? A: Batch/coalesce updates on client and cap queue growth with drop or snapshot policies.
Q3: Can you migrate from SSE to WebSocket later? A: Yes, keep a transport adapter boundary so UI logic remains protocol-agnostic.
Implementation checklist / one-sentence answer
Use SSE for simple server-to-client streaming over HTTP; use WebSocket for true bidirectional, high-frequency interaction. Validate the choice with connection lifecycle, infra cost, and failure-recovery requirements.