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.

Java Architect Handbook
Java Architect Handbook
Java Architect Handbook
Is WebSocket Still the Best Choice for Real-Time Push? Compare with SSE and Polling

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:

WebSocket browser compatibility
WebSocket browser compatibility

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:

SSE browser compatibility
SSE browser compatibility

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.readyState

0 – 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 flag

Refer 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 server

Project directory structure:

Project directory
Project directory

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

FrontendNode.jsWebSocketExpressReal‑time communicationServer‑Sent EventsPollingSSE
Java Architect Handbook
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.