Is WebSocket Still the Best Choice for Real-Time Push? Compare with SSE and Polling
This article examines three server‑to‑client push methods—polling, WebSocket, and Server‑Sent Events (SSE)—detailing their mechanisms, browser compatibility, pros and cons, suitable scenarios, and provides step‑by‑step demos with Node.js/Express and plain HTML to help developers choose the most efficient solution for real‑time messaging.
Implementation Options for Server‑to‑Client Push
In everyday development we often need the server to actively push data to the client, such as real‑time dashboards, unread message notifications, or chat features.
Polling
WebSocket
Server‑Sent Events (SSE)
Polling Overview
Polling creates the illusion of push by repeatedly sending HTTP requests from the client. Each request still goes through the full TCP handshake, consuming unnecessary resources, occupying a browser's limited concurrent connections (e.g., Chrome allows only six per domain), and may introduce latency when the interval is long.
Drawbacks of polling:
Repeated HTTP handshake for every request.
Continuous client processing from page load.
Consumes a concurrent connection slot for the duration of the poll.
Potentially delayed data retrieval.
WebSocket Overview
WebSocket is a full‑duplex protocol (ws/wss) that enables bidirectional communication between client and server. It is powerful but introduces a new protocol that not all browsers may support and adds complexity compared to HTTP‑based solutions.
Browser compatibility chart:
SSE Overview
SSE is a single‑direction, long‑lived HTTP/1.1 connection that allows the server to push data to the browser. It uses the existing HTTP infrastructure, so most servers support it out of the box. It is lightweight, consumes fewer resources, and automatically handles reconnection.
Key points:
Only server‑to‑client communication.
Built on HTTP/HTTPS, no extra server support needed.
IE does not support SSE.
Browser compatibility chart:
WebSocket vs SSE
Polling
Polling is a fallback when both WebSocket and SSE are unavailable, which is rare in modern browsers.
WebSocket and SSE
Both are common choices for server‑client communication, but each excels in different scenarios.
WebSocket: full‑duplex, stronger functionality, heavier protocol.
SSE: single‑direction, lighter, easier to deploy on existing HTTP servers.
SSE provides automatic reconnection; WebSocket requires additional handling.
SSE can send custom data types.
Suitable Business Scenarios
SSE is ideal when only the server needs to push data, such as real‑time dashboards or notification centers.
WebSocket shines in bidirectional use cases like chat applications where the client also sends messages to the server.
SSE Core API
Establish an SSE connection:
var source = new EventSource(url);SSE Connection States
source.readyState0 – CONNECTING: connection not yet established or disconnected.
1 – OPEN: connection established, ready to receive data.
2 – CLOSED: connection closed and will not reconnect.
SSE Events
open– triggered when the connection opens. message – triggered when data arrives. error – triggered on communication errors (e.g., disconnection).
Data Format
Content-Type: text/event-stream // text response format
Cache-Control: no-cache // prevent caching
Connection: keep-alive // keep‑alive flagRefer to the official SSE documentation for more details.
Demo: Building an SSE Connection
The demo uses a plain HTML page (no framework) for the front end and Node.js with Express for the back end.
Create index.html with the front‑end code and open it in a browser.
Create index.js with the back‑end code, then run the following commands in its directory:
npm init // initialize npm
npm i express // install Express
node index // start the serverProject directory structure:
After these steps the demo runs and streams timestamps from the server to the browser.
Front‑End Demo Code
<!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>Document</title>
</head>
<body>
<ul id="ul"></ul>
<script>
// generate li element
function createLi(data) {
let li = document.createElement("li");
li.innerHTML = String(data.message);
return li;
}
// check SSE support
let source = '';
if (window.EventSource) {
source = new EventSource('http://localhost:8088/sse/');
} else {
throw new Error("Current browser does not support SSE");
}
// connection opened
source.onopen = function(event) {
console.log(source.readyState);
console.log("Long connection opened");
};
// receive message
source.onmessage = function(event) {
console.log(JSON.parse(event.data));
console.log("Received long‑connection data");
let li = createLi(JSON.parse(event.data));
document.getElementById('ul').appendChild(li);
};
// connection error
source.onerror = function(event) {
console.log(source.readyState);
console.log("Long connection error");
};
</script>
</body>
</html>Back‑End Demo Code (Node + Express)
const express = require('express'); // import framework
const app = express(); // create app
const port = 8088; // server port
// enable CORS
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', // data type
'Cache-Control': 'no-cache', // no caching
'Connection': 'keep-alive' // keep‑alive flag
});
console.log('Entered long connection');
setInterval(() => {
console.log('Sending data continuously');
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}`);
});Conclusion
SSE is lighter than WebSocket.
SSE runs over HTTP/HTTPS, requiring no extra server support.
WebSocket introduces a new ws/wss protocol.
Use SSE when only the server pushes data.
Choose WebSocket for bidirectional communication.
Both have good browser compatibility (except IE for SSE).
Polling is the least efficient option and should be avoided unless simplicity is paramount.
Mini‑programs do not support SSE.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Handbook
Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.
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.
