Why Polling Is Outdated: Lightweight Real‑Time Push with SSE
The article compares polling, WebSocket, and Server‑Sent Events (SSE), explains why polling is inefficient, outlines the advantages and browser compatibility of SSE versus WebSocket, and provides step‑by‑step Node.js and HTML demos for implementing a real‑time push solution.
Implementation options for server‑to‑client push
Polling
WebSocket
SSE (Server‑Sent Events)
Polling
Polling creates a pseudo‑push by repeatedly sending single‑request HTTP calls from the client to the server. Each request incurs a full TCP handshake and occupies one of the browser's limited concurrent connection slots (e.g., Chrome allows only six concurrent connections per domain). Long‑running polls also keep the client busy handling requests, which is unfriendly for the browser.
Every request requires the HTTP connection setup (three‑way handshake, four‑way termination), causing unnecessary overhead.
The client must continuously handle requests from the moment the page loads.
Browser concurrent‑request limits (e.g., six per domain in Chrome) mean a long‑running poll can block other requests.
Long poll intervals may delay data delivery.
WebSocket
WebSocket is a full‑duplex protocol that enables bidirectional communication between client and server. It introduces a new protocol scheme (ws/wss) that some browsers may not support, and its architecture is more complex than SSE.
Browser compatibility of WebSocket
SSE (Server‑Sent Events)
SSE is a one‑way, long‑connection protocol built on top of HTTP/HTTPS. The server can push data to the browser, reducing client‑side complexity and resource consumption. Because it uses standard HTTP, existing server software supports it without extra configuration.
Browser compatibility of SSE
Note: Internet Explorer does not support SSE.
Differences between WebSocket and SSE
WebSocket is full‑duplex; SSE is single‑direction (server‑to‑client).
WebSocket requires server support for the ws/wss protocol; SSE runs over standard HTTP and is widely supported by existing servers.
SSE is lightweight and simpler; WebSocket is heavier and more complex.
SSE includes automatic reconnection; WebSocket needs additional handling for reconnection.
SSE allows custom data types.
SSE core API
var source = new EventSource(url);SSE connection states
0 – EventSource.CONNECTING : connection not yet established or disconnected.
1 – EventSource.OPEN : connection established and ready to receive data.
2 – EventSource.CLOSED : connection closed and will not reconnect.
SSE events
open– triggered when the connection is opened. message – triggered when data is received. error – triggered on communication errors such as disconnection.
Data format
Content-Type: text/event-stream // text response format
Cache-Control: no-cache // prevent caching
Connection: keep-alive // keep‑alive long connectionDemo: building an SSE service
Setup steps
Create index.html with the front‑end code and open it in a browser.
Create a new folder, add index.js with the back‑end code, then run the commands below.
npm init // initialize npm
npm i express // install Express framework
node index // start the serverFrontend code demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSE Demo</title>
</head>
<body>
<ul id="ul"></ul>
<script>
function createLi(data){
let li = document.createElement("li");
li.innerHTML = String(data.message);
return li;
}
let source = '';
if (!!window.EventSource) {
source = new EventSource('http://localhost:8088/sse/');
} else {
throw new Error("Current browser does not support SSE");
}
source.onopen = function(event) {
console.log(source.readyState);
console.log("Long connection opened");
};
source.onmessage = function(event) {
console.log(JSON.parse(event.data));
console.log("Received message");
let li = createLi(JSON.parse(event.data));
document.getElementById("ul").appendChild(li);
};
source.onerror = function(event) {
console.log(source.readyState);
console.log("Long connection error");
};
</script>
</body>
</html>Backend code demo (Node + Express)
const express = require('express');
const app = express();
const port = 8088;
app.all("*", function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("Access-Control-Allow-Credentials", true);
if (req.method == 'OPTIONS') { res.sendStatus(200); } else { next(); }
});
app.get("/sse", (req, res) => {
res.set({
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
console.log("Entered long‑connection");
setInterval(() => {
const data = { message: `Current time is ${new Date().toLocaleTimeString()}` };
res.write(`data: ${JSON.stringify(data)}
`);
}, 1000);
});
app.listen(port, () => {
console.log(`Server started – http://localhost:${port}`);
});Result
When to use each technology
Use SSE when only the server needs to push messages (e.g., real‑time dashboards, notification centers).
Use WebSocket for bidirectional communication such as chat applications.
Both have good browser compatibility except that Internet Explorer does not support SSE.
Polling is the least desirable option due to high client resource consumption.
java1234
Former senior programmer at a Fortune Global 500 company, dedicated to sharing Java expertise. Visit Feng's site: Java Knowledge Sharing, www.java1234.com
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
