Server-Sent Events (SSE) let a server push updates to a web page over a single, long-lived HTTP connection. This is ideal for live news tickers, sports scores, stock prices, notifications, and dashboards—anywhere the browser needs fresh data without constantly asking the server “anything new yet?”
SSE is simpler than WebSockets when you only need server → client communication. This tutorial covers the wire format, a Node.js server, the browser EventSource API, and minimal Try It demos you can run without setting up a backend.
What You’ll Learn
01
SSE format
data: lines.
02
Node server
event-stream.
03
EventSource
Client API.
04
Reconnect
Auto retry.
05
Event types
Named events.
06
Security
HTTPS & CORS.
Fundamentals
What Are Server-Sent Events?
Server-Sent Events (SSE) is a web technology where the server sends updates to the client as they happen. The client opens one HTTP connection and keeps it open; the server writes new messages whenever data changes.
Unlike polling (repeated fetch calls every few seconds), SSE is efficient: one connection, many updates. Unlike WebSockets, SSE is text-based, works through most HTTP proxies, and only flows in one direction—which is exactly what many live feeds need.
💡
Beginner Tip
Think of SSE like a radio broadcast: the server transmits, your page listens. You do not send messages back through the same SSE connection (use fetch or WebSockets for client → server).
Architecture
How Do Server-Sent Events Work?
SSE works over ordinary HTTP. The server responds with Content-Type: text/event-stream and keeps the connection open. Each message is plain text with a simple structure:
data: — the payload (one or more lines; required for default messages).
event: — optional event name (defaults to message).
id: — optional id so the client can resume after reconnect.
retry: — optional reconnection delay in milliseconds.
Blank line — two newline characters (\n\n) end each event.
Example on the wire:
SSE wire format
data: Stock price is 142.50
event: alert
data: Trading halted
The browser’s EventSource parses this stream and fires JavaScript events you can handle.
Server
Setting Up Server-Sent Events
On the server, set headers for a streaming response and write data: lines followed by a blank line. Flush output so the client receives events immediately.
Here is a minimal Node.js example that sends the current time every second:
js
const http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
var timer = setInterval(function () {
res.write('data: ' + new Date().toLocaleTimeString() + '\n\n');
}, 1000);
req.on('close', function () {
clearInterval(timer);
});
}).listen(8080, function () {
console.log('SSE server on http://localhost:8080');
});
Run with node sse-server.js, then point your page’s EventSource at http://localhost:8080.
Client
Receiving Events on the Client Side
Use the EventSource API in the browser. The default message event fires for plain data: lines:
js
var eventSource = new EventSource('http://localhost:8080');
eventSource.onmessage = function (event) {
console.log('New message:', event.data);
};
eventSource.onopen = function () {
console.log('SSE connection opened');
};
Call eventSource.close() when the page no longer needs updates (for example when navigating away).
Reliability
Reconnecting Automatically
A key feature of SSE is automatic reconnection. If the network drops, EventSource retries after a short delay. Listen for errors to show status in your UI:
The server can suggest a retry interval with retry: 3000\n\n (wait 3 seconds before reconnecting).
Advanced
Handling Different Event Types
Send a named event from the server with the event: field. On the client, use addEventListener instead of onmessage:
js
// Server
res.write('event: customEvent\n');
res.write('data: This is a custom event\n\n');
js
// Client
eventSource.addEventListener('customEvent', function (event) {
console.log('Custom event:', event.data);
});
Default unnamed events still trigger onmessage. Named events do not.
Safety
Security Considerations
SSE rides on HTTP, so apply the same security practices as any web API:
Use HTTPS in production so stream data cannot be read or modified on the network.
Validate and escape data before inserting into HTML—treat event.data like any untrusted string (use textContent, not innerHTML).
Authenticate streams when content is private (cookies or tokens on the same origin).
Configure CORS if the EventSource URL is on a different domain than your page.
Rate-limit connections on the server to prevent abuse of open streams.
Cheat Sheet
⚡ Quick Reference
Task
Code / format
Server content type
text/event-stream
Send one message
res.write('data: hello\\n\\n')
Named event
event: name\\ndata: payload\\n\\n
Open stream (client)
new EventSource(url)
Default messages
es.onmessage = fn
Named messages
es.addEventListener('name', fn)
Close stream
es.close()
Server
data: ...\n\n
Wire format
Client
EventSource
Browser API
Direction
server → client
One-way
Retry
automatic
Built-in
Hands-On
Examples Gallery
Five short examples from server setup to a full clock page. Try It Yourself demos use plain HTML with no CSS and simulate the stream so you can practice client handlers without running Node.js.
Run the Node server from Example 1, open this HTML page, and the clock updates every second from the stream.
Applications
🚀 Common Use Cases
Live news and sports tickers — push headlines as they publish.
Stock and crypto prices — stream price changes to dashboards.
Notifications — alert users without polling every few seconds.
Progress updates — long server jobs report status (% complete).
Social feeds — new posts appear at the top in real time.
Monitoring dashboards — server metrics streamed to ops teams.
🧠 How SSE Works (Step by Step)
1
Client opens stream
new EventSource(url) starts an HTTP GET.
Connect
2
Server sets headers
text/event-stream keeps connection alive.
Stream
3
Server writes events
data: ...\n\n for each update.
Push
4
Browser fires events
onmessage or addEventListener.
Handle
=
📡
Live UI
Page updates without refresh or polling.
Important
📝 Notes
SSE is one-way—only server → client on that connection.
Internet Explorer does not support EventSource; all modern browsers do.
Some older proxies buffer responses; SSE needs streaming-friendly infrastructure.
Browser limit: roughly six SSE connections per domain (similar to HTTP/1.1).
For bidirectional chat or games, consider WebSockets instead.
Try It demos simulate streams so you can learn handlers without a backend.
Compatibility
Universal Browser Support
EventSource is supported in Chrome, Firefox, Safari, Edge, and other modern browsers. It is not available in Internet Explorer. For legacy IE, use polling or a polyfill library.
✓ Baseline · Since HTML
Server-Sent Events API
EventSource is supported in Chrome, Firefox, Safari, Edge, and other modern browsers. It is not available in Internet Explorer. For legacy IE, use polling or a polyfill library.
94%Modern browser support
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
Server-Sent Events APIExcellent
Bottom line: Safe for modern web apps. Use HTTPS and test behind your production CDN/proxy.
Pro Tips
💡 Best Practices
✅ Do
Use SSE when only the server needs to push data
Set text/event-stream and disable caching on the server
Close EventSource when leaving the page
Parse JSON safely from event.data
Use named events for different update types
Serve streams over HTTPS in production
❌ Don’t
Use SSE for two-way real-time chat (use WebSockets)
Insert raw event.data into HTML with innerHTML
Forget to clear server timers when clients disconnect
Send huge payloads on every tick without throttling
Assume IE support without a fallback
Open dozens of EventSource connections per page
Wrap Up
Conclusion
Server-Sent Events offer a straightforward way to implement real-time updates in web applications. The server writes data: lines over HTTP; the browser listens with EventSource and updates the UI in onmessage.
You get automatic reconnection, simple text format, and no WebSocket infrastructure. Try the demos, run the Node.js server locally, and build responsive apps that keep users updated without constant polling.
Use these points when choosing server push for your app.
5
Core concepts
📡01
One-way
Server push.
Model
📄02
data:\n\n
Wire format.
Format
💻03
EventSource
Client API.
Browser
🔄04
Auto retry
Reconnects.
Reliable
🔒05
HTTPS
Production.
Security
❓ Frequently Asked Questions
SSE is a web standard for pushing text updates from a server to a browser over a single long-lived HTTP connection. The client uses the EventSource API to listen; the server sends messages in a simple text format (data: ... followed by a blank line).
SSE is one-way (server to client only) and runs over ordinary HTTP. WebSockets are two-way and use a different protocol. Choose SSE for live feeds, notifications, and dashboards where only the server sends updates.
EventSource is the browser interface for SSE. You call new EventSource(url) and listen with onmessage or addEventListener. The browser handles reconnection automatically if the connection drops.
Set Content-Type to text/event-stream, plus Cache-Control: no-cache and Connection: keep-alive. Each message is text lines ending with a blank line, for example: data: Hello followed by two newline characters.
Yes. Put JSON in the data line as a string: data: {"price":42}. On the client, parse it with JSON.parse(event.data) inside your onmessage handler.
For production, yes—use HTTPS to protect data in transit. Local development on http://localhost is fine for learning. Also configure CORS if the EventSource URL is on a different origin.
Did you know?
SSE uses the same HTTP port as normal web pages (80/443), so it often works through corporate firewalls that block WebSockets. That is one reason teams pick SSE for simple live dashboards before adopting full duplex protocols.