When to Choose SSE, WebSocket, or Polling: A Practical Comparison

This article examines three server‑to‑client push techniques—polling, WebSocket, and Server‑Sent Events (SSE)—by detailing their mechanisms, listing concrete drawbacks and advantages, comparing them side‑by‑side, and providing step‑by‑step Node.js demos for real‑time dashboards and chat scenarios.

Java Web Project
Java Web Project
Java Web Project
When to Choose SSE, WebSocket, or Polling: A Practical Comparison

Typical server‑push scenarios

Real‑time dashboards, unread‑message notifications, and chat messages often require the server to actively push data to the client.

Implementation options

Polling (pseudo‑push)

WebSocket (full‑duplex)

Server‑Sent Events (SSE, one‑way)

Polling overview

Polling repeatedly sends a single‑direction HTTP request from the client; the server merely replies, creating the illusion of push.

Drawbacks of polling

Each request incurs a full TCP handshake (three‑way) and teardown (four‑way), adding unnecessary overhead.

The client must keep a request open from page load onward, continuously consuming browser resources.

Browsers limit concurrent connections per host (e.g., Chrome caps at six). A long‑running poll occupies one slot, potentially blocking other resources.

Long‑running polls may introduce latency because data is only delivered at the next poll interval.

WebSocket overview

WebSocket establishes a full‑duplex channel (ws/wss) that allows both client and server to send messages at any time. It provides richer functionality but requires server support for the ws protocol and adds protocol complexity.

SSE overview

SSE is a lightweight, single‑direction protocol built on standard HTTP/HTTPS. The server can push data without the client sending messages back. Because it reuses the existing HTTP stack, any HTTP‑capable server can serve SSE without extra configuration. The trade‑off is the lack of client‑to‑server messaging.

Compatibility note : Internet Explorer does not support SSE, and mini‑program environments (e.g., WeChat Mini‑Program) also lack support.

WebSocket browser compatibility
WebSocket browser compatibility
SSE browser compatibility
SSE browser compatibility

Official comparison (SSE vs WebSocket)

WebSocket is full‑duplex; SSE is server‑to‑client only.

WebSocket requires server support for the ws protocol; SSE runs over HTTP, so any existing server works.

SSE is lightweight and simple; WebSocket is heavier and more complex.

SSE includes built‑in reconnection; WebSocket needs custom handling.

SSE allows custom data types.

Business‑scenario mapping

When the requirement is one‑way push—e.g., real‑time dashboards or message‑center notifications—SSE is optimal because it is light and has broad server support.

When bidirectional communication is needed—e.g., chat applications where the client also sends messages—WebSocket is preferable.

SSE core API

var source = new EventSource(url);

SSE connection states

0 ( EventSource.CONNECTING): connection not yet established or has been lost.

1 ( EventSource.OPEN): connection is open and can receive data.

2 ( EventSource.CLOSED): connection closed and will not reconnect.

SSE events

open : fired when the connection is established.

message : fired when a data chunk arrives.

error : fired on communication errors such as disconnection.

Data format

Content-Type: text/event-stream   // plain‑text response
Cache-Control: no-cache         // prevent caching
Connection: keep-alive          // keep the long‑lived connection

Demo walk‑through

Create index.html with the front‑end demo code (see below) and open it in a browser.

Create a new folder, add index.js with the back‑end Express demo (see below), then run the server.

Initialize the project and start the server:

npm init          // initialize npm
npm i express    // install Express
node index        // launch the service

Front‑end demo (index.html)

<!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(){
      console.log(source.readyState);
      console.log("Connection opened");
    };
    source.onmessage = function(event){
      const data = JSON.parse(event.data);
      console.log(data);
      document.getElementById('ul').appendChild(createLi(data));
    };
    source.onerror = function(){
      console.log(source.readyState);
      console.log("Connection error");
    };
  </script>
</body>
</html>

Back‑end demo (Node.js + Express)

const express = require('express');
const app = express();
const port = 8088;
// CORS configuration
app.all('*', (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)}

`);
    console.log('Sent data');
  }, 1000);
});
app.listen(port, () => {
  console.log(`Server started – http://localhost:${port}`);
});

Result

Running the two snippets opens a persistent connection; the browser list updates every second with the current time, demonstrating a functional SSE stream.

Conclusion

SSE is lighter than WebSocket.

SSE operates over HTTP/HTTPS, so existing servers support it out of the box.

WebSocket introduces a new ws/wss protocol and requires explicit server support.

For one‑way server‑to‑client push, SSE is recommended.

For bidirectional communication, choose WebSocket.

Both SSE and WebSocket have good browser compatibility, except IE (no SSE) and mini‑program environments (no SSE).

Polling should be a last resort because it consumes client resources heavily.

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.

JavaScriptNode.jsWebSocketExpressServer PushPollingSSE
Java Web Project
Written by

Java Web Project

Focused on Java backend technologies, trending internet tech, and the latest industry developments. The platform serves over 200,000 Java developers, inviting you to learn and exchange ideas together. Check the menu for Java learning resources.

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.