Articles

Server-Sent Events vs WebSockets: Which to Use

SSE streams one-way updates over plain HTTP; WebSockets open a full-duplex channel. How they differ and which fits your real-time feature.

Takina Takina · · 5 min read
A connected globe network

Server-Sent Events (SSE) and WebSockets both push real-time updates from a server to a browser without the client polling for them, but they solve different shapes of problem. SSE is a one-way stream built on plain HTTP; WebSockets are a full-duplex, bidirectional connection over their own protocol. Picking between them comes down to a single question: does the client need to send data back over the same connection, or just receive it?

How each one works

Server-Sent Events are just a long-lived HTTP response. The client opens a connection with EventSource, the server keeps it open, and writes text-formatted events to it whenever it has new data. Because it rides on ordinary HTTP, it inherits things HTTP already does well: automatic reconnection with a Last-Event-ID header so a dropped connection can resume where it left off, standard proxy and load-balancer compatibility, and no separate protocol handshake beyond the normal HTTP request.

WebSockets start as an HTTP request too, but immediately upgrade to a different protocol (ws:// or wss://) via the Upgrade header. Once upgraded, either side can send messages at any time — the server pushes data, and the client can push data right back over the same socket, with no request/response cycle needed for either direction.

The comparison

Server-Sent EventsWebSockets
DirectionOne-way: server to clientFull-duplex: both directions
ProtocolPlain HTTPOwn protocol (ws/wss), after an HTTP upgrade
Message formatText (UTF-8) onlyText or binary
ReconnectionAutomatic, built into EventSourceManual — you write the retry logic
Proxy/firewall friendlinessHigh — looks like a normal HTTP responseLower — some older proxies mishandle the upgrade
Browser API complexityMinimal (EventSource)Slightly more (WebSocket, manual message framing)
Typical use caseLive feeds, notifications, progress updatesChat, multiplayer, collaborative editing

When SSE is the better fit

If the data only flows one direction — a live score ticker, a build-progress log streaming to a dashboard, a notification feed, or streaming an LLM’s response token by token — SSE is usually the simpler, more robust choice. It needs no special server framework support beyond writing a specific content type, it survives flaky networks better because reconnection is automatic, and it plays nicely with existing HTTP infrastructure like load balancers and CDNs that already know how to handle streaming responses. Any request the client needs to make (start a job, change a filter) just goes over a normal HTTP request alongside the SSE stream.

When WebSockets are the better fit

If the client needs to send frequent, low-latency messages back — a chat app, a multiplayer game, a collaborative document editor, or a trading interface where the client submits orders and receives fills over the same channel — WebSockets avoid the overhead of opening a new HTTP request for every client-to-server message. The full-duplex channel also supports binary frames directly, which matters for anything moving non-text payloads efficiently.

Authentication and reconnection in practice

SSE authenticates the same way any HTTP request does — cookies or an Authorization header travel with the initial request, and the browser’s native EventSource API handles reconnection for you, replaying the last event ID so the server can resume the stream where it left off rather than replaying everything from the start. WebSockets need this handled manually: the initial handshake can carry a cookie or token, but if the connection drops, the application code is responsible for detecting it, reopening a new connection, and — if messages need to be replayed — re-synchronizing state, since there’s no built-in equivalent of Last-Event-ID. That extra responsibility is a fair trade for full-duplex communication, but it’s worth budgeting for when choosing WebSockets purely out of habit rather than necessity.

A note on HTTP/2 and multiplexing

One reason SSE fell out of favor briefly, and is now favored again, involves the underlying HTTP version. HTTP/1.1 connections are capped at roughly six per origin in most browsers, so multiple SSE streams to the same origin could exhaust that limit alongside ordinary page requests. HTTP/2 (and HTTP/3) fixed this by multiplexing many streams over a single connection, removing that constraint — one more reason SSE is a practical default today rather than a legacy fallback.

Scaling either one on the server

Both approaches require the server to hold a connection open per connected client, which changes how a backend needs to scale compared to stateless request/response APIs. A server handling thousands of open SSE streams or WebSocket connections needs an architecture built for long-lived connections — typically an event-driven or async I/O model rather than one thread per request — and load balancers in front of either need to be configured for sticky sessions or connection-aware routing, since a reconnect landing on a different backend instance than the one holding relevant in-memory state can behave unexpectedly. This operational cost applies to both technologies roughly equally; it’s not a factor that favors one over the other, but it’s easy to underestimate when a feature that worked fine in local testing suddenly needs to hold ten thousand simultaneous connections in production.

Neither replaces polling everywhere

Both are overkill for data that changes rarely — a dashboard that refreshes every few minutes is usually better served by a plain periodic fetch, which is simpler to reason about and doesn’t hold a connection open unnecessarily. Reach for SSE or WebSockets when updates are frequent and latency actually matters to the user experience.

The takeaway

Choose Server-Sent Events when the server needs to push updates and the client doesn’t need to talk back over the same channel — it’s simpler, reconnects automatically, and rides on ordinary HTTP. Choose WebSockets when both sides need to exchange messages continuously and in real time. Neither is a universal upgrade over the other; match the tool to whether your data actually needs to flow both ways.

Takina Takina · · 4 min read

What Is WebRTC? Real-Time Audio, Video, and Data

WebRTC lets browsers stream audio, video, and data directly between peers — no plugins. How getUserMedia, RTCPeerConnection, and ICE/STUN/TURN fit together.

#Web Development #Networking #JavaScript
Takina Takina · · 4 min read

What Is a WebSocket? Real-Time, Two-Way Web Communication

A WebSocket is a protocol for full-duplex, persistent communication over a single TCP connection. Learn how it works, when to use it, and what the alternatives are.

#Web Development #JavaScript #Networking
Takina Takina · · 4 min read

TypeScript Abstract Classes, Explained

Abstract classes in TypeScript define shared implementation plus methods subclasses must fill in. How they differ from interfaces and when to reach for them.

#TypeScript #JavaScript #Web Development