Is WebSocket Still the Best Choice for Real‑Time Push? A Comparison with Server‑Sent Events

The article compares polling, WebSocket, and Server‑Sent Events for server‑to‑client real‑time messaging, explains the advantages and drawbacks of each, and provides a complete Node.js/Express and plain‑HTML demo showing how to implement SSE as a lightweight alternative to WebSocket.

SpringMeng
SpringMeng
SpringMeng
Is WebSocket Still the Best Choice for Real‑Time Push? A Comparison with Server‑Sent Events

Introduction

In many development scenarios the server needs to push data to the client, such as real‑time dashboards, unread message notifications, or chat.

This article introduces Server‑Sent Events (SSE), compares it with polling and WebSocket, and provides a complete demo using a static HTML page and a Node.js/Express backend.

Implementation options for server‑to‑client push

Polling

WebSocket

SSE

Polling overview

Polling creates the illusion of push by repeatedly sending HTTP requests from the client. It is essentially a “pseudo‑push” because the server only responds to client‑initiated requests.

Drawbacks of polling:

Each request requires a full HTTP handshake, consuming unnecessary resources.

The client must keep sending requests from page load, which is unfriendly even if each request is lightweight.

Browsers limit concurrent connections per host (e.g., Chrome allows six); a long‑lived poll occupies one slot.

Long polling intervals may cause noticeable latency.

WebSocket overview

WebSocket is a full‑duplex protocol that allows bidirectional communication between client and server. Its advantages are strong functionality and support for real‑time interaction.

Its disadvantages are that it is a newer protocol (ws/wss) and not all browsers support it out of the box. Compared with SSE, WebSocket is heavier because of its richer feature set.

Browser compatibility of WebSocket

WebSocket compatibility
WebSocket compatibility

SSE overview

SSE is a unidirectional, long‑living HTTP/1.1 connection that lets the server push data to the client but does not allow the client to send messages.

Long connections are a persistent HTTP/1.1 technique that allows multiple requests/responses over a single TCP connection, reducing server load and improving performance.

Advantages of SSE: lightweight protocol, lower client overhead, uses standard HTTP so existing servers support it without extra configuration.

Note: Internet Explorer does not support SSE.

SSE browser compatibility

SSE compatibility
SSE compatibility

WebSocket vs SSE

Polling

In modern browsers both WebSocket and SSE are widely supported; polling is only a fallback when neither is available.

WebSocket and SSE

Both are common choices. Neither is universally superior; the best choice depends on the business scenario.

WebSocket provides full‑duplex communication.

SSE runs over HTTP and is supported by all standard server software.

SSE is simpler and lighter, while WebSocket is more complex.

SSE includes automatic reconnection; WebSocket requires additional handling.

SSE allows custom data types.

Typical use cases

SSE is ideal for scenarios that only require server‑to‑client push, such as real‑time dashboards or notification centers.

WebSocket is ideal for bidirectional use cases like chat, where the client also needs to send messages.

SSE main APIs

var source = new EventSource(url);

SSE connection states

0 (EventSource.CONNECTING): connection not yet established or disconnected.

1 (EventSource.OPEN): connection established, 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 arrives.

error – triggered on communication errors.

Data format

Content-Type: text/event-stream // text response format
Cache-Control: no-cache  // do not cache
Connection: keep-alive // long‑connection flag

Demo: How to build an SSE connection

The front‑end demo uses a plain HTML page without any framework. The back‑end uses Node.js with Express.

Create index.html and paste the front‑end code.

Create a new folder, add index.js with the back‑end code, then run:

npm init
npm i express
node index

Run the commands in the project folder to start the service.

Front‑end 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>Document</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("当前浏览器不支持SSE");
    }
    source.onopen = function(event) {
      console.log(source.readyState);
      console.log("长连接打开");
    };
    source.onmessage = function(event) {
      console.log(JSON.parse(event.data));
      console.log("收到长连接信息");
      let li = createLi(JSON.parse(event.data));
      document.getElementById("ul").appendChild(li);
    };
    source.onerror = function(event) {
      console.log(source.readyState);
      console.log("长连接中断");
    };
  </script>
</body>
</html>

Back‑end 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("进入到长连接了");
  setInterval(() => {
    console.log("正在持续返回数据中ing");
    const data = { message: `Current time is ${new Date().toLocaleTimeString()}` };
    res.write(`data: ${JSON.stringify(data)}

`);
  }, 1000);
});

app.listen(port, () => {
  console.log(`项目启动成功-http://localhost:${port}`);
});

Result

Demo result
Demo result

Conclusion

SSE is lighter than WebSocket.

SSE is based on HTTP/HTTPS.

WebSocket uses the ws/wss protocol.

Use SSE when only server‑to‑client push is needed.

Use WebSocket for bidirectional communication.

Both have good browser support, except IE does not support SSE.

Polling is a last‑resort solution, though it can be convenient for quick tests.

Author: 工边页字 (source: juejin.cn/post/7325730345840066612)

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.

Node.jsWebSocketExpressServer‑Sent Eventsreal‑time pushSSEEventSource
SpringMeng
Written by

SpringMeng

Focused on software development, sharing source code and tutorials for various systems.

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.