When developers hear "real-time," their first instinct is usually to reach for WebSockets. But what if I told you that for many use cases, WebSockets are actually overkill?
If you are building a chat application or a multiplayer game where the client and server constantly talk to each other, WebSockets are perfect. However, if you are building a live metrics dashboard, a stock ticker, or a news feed, the communication is strictly one-way: the server pushes updates to the client.
For these unidirectional streams, Server-Sent Events (SSE) are a much better architectural choice.
In this tutorial, I'll show you how I built a lightweight, real-time server dashboard using Node.js and native SSE—no heavy libraries required.
🧠 Why SSE over WebSockets?
Native HTTP: SSE operates over standard HTTP/HTTPS. You don't need custom protocols, complex proxy configurations, or firewall bypasses.
Auto-Reconnect: The browser's native API handles connection drops and retries automatically out of the box.
Resource Efficiency: It uses a single, long-lived HTTP connection, making it much lighter on server resources for one-way data broadcasting.
🛠️ Step 1: The Node.js Backend
We need a simple Express server that configures the specific headers required for an SSE stream (text/event-stream).
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/events', (req, res) => {
// 1. Mandatory SSE Headers
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// 2. Push data to the client every 3 seconds
const intervalId = setInterval(() => {
const data = JSON.stringify({
message: "System update notification",
activeUsers: Math.floor(Math.random() * (500 - 100 + 1) + 100),
cpuLoad: (Math.random() * 100).toFixed(1) + "%",
timestamp: new Date().toISOString()
});
// Note: The SSE format strictly requires "data: " and TWO newlines
res.write(`data: ${data}\n\n`);
}, 3000);
// 3. Clean up when the client disconnects
req.on('close', () => {
clearInterval(intervalId);
});
});
app.listen(3000, () => console.log('SSE Server running!'));
💻 Step 2: The Vanilla JS Frontend
The best part about SSE is that you don't need any external libraries on the frontend. Modern browsers have the EventSource API built-in.
// Connect to the backend stream
const eventSource = new EventSource('http://localhost:3000/events');
// Listen for incoming messages
eventSource.onmessage = function(event) {
// Parse the JSON payload from the server
const data = JSON.parse(event.data);
console.log(`Update at ${data.timestamp}: CPU is at ${data.cpuLoad}`);
// Here you would dynamically update your DOM elements
};
// Handle connection errors (the browser will auto-reconnect!)
eventSource.onerror = function(error) {
console.error('SSE Error:', error);
};
🏁 Conclusion
While WebSockets often steal the spotlight, Server-Sent Events remain one of the most elegant, efficient, and underutilized tools in a backend developer's arsenal for real-time, one-way data streaming.
You can check out the full source code and the complete UI dashboard in My GitHub Repository Here.
Have you used SSE in production? Let me know in the comments!
I'm Marcela Zapata Vanegas, Technical Writer & Full Stack Developer. I specialize in building and documenting cloud-native solutions.
Top comments (0)