Last Updated: January 9, 2026
Lets say you are building a dashboard that displays live stock prices. Every second, prices change, and users expect to see updates without refreshing the page. The data flows one direction: from your servers to the browser. Users watch the numbers tick, but they do not send stock prices back.
This is a common pattern. Live sports scores, build pipeline status, social media feeds, breaking news alerts. Data streams from server to client, and the client just listens.
WebSockets can handle this, but they feel like overkill. You do not need bidirectional communication. You do not want to manage a custom protocol. You just want the server to push updates to the browser.
Server-Sent Events (SSE) is designed exactly for this scenario. It provides a simple, standardized way for servers to push data to browsers over a single HTTP connection.
The browser handles reconnection automatically. The protocol is text-based and easy to debug. And it works with your existing HTTP infrastructure.
In this chapter, we will explore:
Server-Sent Events is a web technology that allows servers to push updates to clients over a persistent HTTP connection. Unlike traditional request-response HTTP where the client initiates every exchange, SSE flips the model: the client opens a connection once, and the server sends data whenever it wants.
The key characteristics of SSE:
Think of SSE as a one-way radio broadcast. The server is the radio station, continuously transmitting. Clients tune in and listen. They cannot talk back through the same channel, but that is fine because they just need to receive.
SSE sits in a specific spot on the real-time communication spectrum. Understanding where it fits helps you choose the right tool.
| Aspect | Long Polling | SSE | WebSocket |
|---|---|---|---|
| Direction | Server to client | Server to client | Bidirectional |
| Protocol | HTTP (repeated) | HTTP (streaming) | WebSocket protocol |
| Connection per message | New request each time | Single persistent | Single persistent |
| Browser API | fetch/XMLHttpRequest | EventSource | WebSocket |
| Auto-reconnect | Manual implementation | Built-in | Manual implementation |
| Message format | Any | Text only | Text or binary |
| HTTP/2 multiplexing | Yes | Yes | No |
The comparison with long polling is particularly interesting. Both deliver near real-time updates from server to client. But they work differently:
Long polling creates a new HTTP request for each message. SSE streams multiple messages over a single connection. This makes SSE more efficient for high-frequency updates and eliminates the reconnection gap where messages could be missed.
SSE uses a remarkably simple text-based protocol. The server responds with content type text/event-stream and sends events as plain text separated by blank lines.
Each event consists of field-value pairs, one per line:
A blank line signals the end of an event. Here is a concrete example:
| Field | Required | Purpose |
|---|---|---|
data | Yes | The event payload. Multiple data lines are concatenated with newlines |
event | No | Event type name. Defaults to "message" if omitted |
id | No | Unique identifier for resumption after reconnection |
retry | No | Tells browser how long (ms) to wait before reconnecting |
For payloads that span multiple lines, use multiple data fields:
The browser concatenates these with newline characters, producing: "Line 1 of the log message\nLine 2 of the log message\nLine 3 of the log message".
Lines starting with a colon are comments and are ignored by the client. These are useful for keeping connections alive:
Browsers provide the EventSource API for consuming SSE streams. It handles connection management, parsing, and reconnection automatically.
The EventSource object tracks connection state through the readyState property:
| State | Value | Meaning |
|---|---|---|
CONNECTING | 0 | Connection is being established or reconnecting |
OPEN | 1 | Connection is open, receiving events |
CLOSED | 2 | Connection is closed, will not reconnect |
The most powerful feature of SSE is built-in automatic reconnection with message resumption. This is functionality you would have to build yourself with WebSockets or long polling.
When the connection drops (network issue, server restart, proxy timeout), the browser:
retry field)Last-Event-ID header with the last received event IDThe server receives the Last-Event-ID header and should return any events that occurred after that ID:
The server can suggest a retry interval by sending the retry field:
This tells the browser to wait 5 seconds before attempting to reconnect after a disconnection. Use longer intervals during known maintenance windows or server overload situations.
Implementing an SSE server requires attention to connection management, event formatting, and keeping connections alive.
Proxies and load balancers may close idle connections. Send periodic heartbeat comments to keep the connection active:
For production systems with multiple server instances, you need a pub/sub layer to distribute events:
Each server subscribes to a Redis channel. When an event producer publishes, all servers receive it and forward to their connected clients.
This comparison comes up frequently. Here is a framework for deciding:
| Factor | SSE | WebSocket |
|---|---|---|
| Complexity | Lower | Higher |
| Browser reconnection | Automatic | Manual |
| Works with HTTP/2 | Yes (multiplexed) | No (separate connection) |
| Proxy/CDN friendly | Yes | Sometimes blocked |
| Message overhead | ~50 bytes | 2-14 bytes |
| Client sends data | Separate HTTP request | Same connection |
Many teams default to WebSockets when SSE would serve them better. If your data flow is primarily server-to-client, try SSE first. You can always upgrade to WebSockets if you outgrow it.
Server-Sent Events provide an elegant solution for server-to-client streaming that is often overlooked in favor of WebSockets.
Last-Event-ID automatically. This is significant functionality you would need to build yourself with WebSockets.For dashboards, feeds, notifications, and any scenario where the server broadcasts and clients listen, SSE delivers real-time updates with minimal complexity.