Definition
Have you ever wondered how websites show you live notifications without you refreshing the page? Or how stock prices update in real-time while you watch? Server-Sent Events (SSE) is one of the simplest ways to achieve this magic. It lets a server push updates to your browser the moment something interesting happens, without you having to ask.
The traditional web model is request-response: your browser asks for data, the server responds, end of conversation. If you want updates, you have to keep asking (polling). SSE flips this for one direction - once you establish a connection, the server can send you updates whenever it wants, for as long as the connection stays open. You make one request, and the server can send you hundreds of updates over the next hour.
What makes SSE special is its simplicity. Unlike WebSockets, which require a protocol upgrade and bidirectional communication setup, SSE works over plain HTTP. It is just a response that never ends - the server keeps the connection open and sends chunks of data whenever it has something new. Browsers have built-in support through the EventSource API, which handles reconnection automatically if the connection drops. For scenarios where you just need one-way updates from server to client, SSE is often the simplest and most reliable choice.
Example
Live sports scores: When you watch a football game on ESPN’s website, SSE can push score updates, play-by-play, and statistics in real-time. You do not refresh - the server sends updates as the game unfolds.
Social media notifications: When someone likes your post or mentions you, SSE can push that notification to your browser instantly. Facebook, Twitter, and LinkedIn all use similar real-time notification systems.
Log streaming: When developers watch server logs in real-time (like in AWS CloudWatch or Heroku logs), SSE often powers that live feed. Each new log line gets pushed to your browser immediately.
Collaborative editing indicators: Google Docs shows you who else is viewing the document. While the actual editing sync uses more complex protocols, presence indicators (who is online) often use SSE-like approaches.
Analogy
The News Ticker: Think of the scrolling news ticker at the bottom of news channels. Once you tune in, updates flow continuously without you doing anything. You do not call CNN every minute asking “any news?” - they push updates when something happens. SSE works the same way.
The Radio Broadcast: When you tune into a radio station, you do not repeatedly request songs. You connect once, and music streams to you continuously. SSE is like radio for data - one connection, continuous updates.
The Airport Departure Board: The departure board updates automatically when flight information changes. You do not have to keep asking the information desk - you just watch the board. SSE creates this same experience for web pages.
The Baby Monitor: Once you turn on a baby monitor, it continuously sends audio to the receiver. You do not have to repeatedly ask “is the baby making noise?” - it just streams when there is something to report. SSE provides this continuous monitoring for server events.
Diagram
sequenceDiagram
participant C as Client
participant S as Server
C->>S: GET /events (Accept: text/event-stream)
Note over C,S: Connection stays open
rect rgb(200, 230, 200)
S-->>C: event: update
data: {"price": 100}
Note right of C: Client receives
S-->>C: event: update
data: {"price": 101}
Note right of C: Client receives
S-->>C: event: alert
data: {"msg": "Breaking news"}
Note right of C: Client receives
end
Note over C,S: Connection drops
C--xS: Network error
Note over C,S: Auto-reconnect
C->>S: GET /events (Last-Event-ID: 3)
S-->>C: event: update
data: {"price": 102}
Code Example
// Client-side SSE
const eventSource = new EventSource('/api/events/stream');
eventSource.addEventListener('price-update', (event) => {
const data = JSON.parse(event.data);
console.log('New price:', data.price);
});
eventSource.onerror = (error) => {
console.error('SSE error:', error);
};
// Server-side (Node.js Express)
app.get('/api/events/stream', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const interval = setInterval(() => {
res.write(`event: price-update\n`);
res.write(`data: {"price": ${Math.random() * 100}}\n\n`);
}, 1000);
req.on('close', () => clearInterval(interval));
});
Security Notes
CRITICAL: Server-Sent Events (SSE) provide one-way push. Less complex than WebSockets.
Protocol:
- HTTP-based: Built on HTTP, not WebSocket
- Persistent connection: Single long-lived HTTP connection
- Server push: Server sends events to client
- Text format: Events in text format (simple)
- Unidirectional: Server to client only
Security:
- Authentication: Require authentication to establish connection
- Authorization: Verify permission before sending events
- Event filtering: Only send events user can receive
- Rate limiting: Limit events per connection
- HTTPS mandatory: Use HTTPS for connection security
Advantages over WebSockets:
- Simpler: No protocol upgrade, easier to understand
- Fallback: Can fallback to polling
- Proxy friendly: Works through HTTP proxies
- Built-in: Browser support without additional libraries
- Automatic reconnection: Browser handles reconnection
Use Cases:
- Notifications: Server-pushed notifications
- Live updates: Real-time updates from server
- Stock prices: Financial data updates
- Chat: One-way messaging (for two-way use WebSocket)
- Monitoring: Server status/log updates
Implementation:
- Content-Type: application/event-stream
- Format: Simple text format with fields
- ID: Include event ID for resume on disconnect
- Reconnection: Specify reconnection timeout
- Error handling: Handle connection failures
Limitations:
- One-way: Cannot send data to server over SSE
- Connection limit: Browsers limit concurrent connections
- Scaling: Difficult to scale to many clients
- Polling: May revert to polling in some networks