Backend Development 13 min read

Server‑Sent Events (SSE) vs WebSocket vs Polling: Usage Scenarios, Advantages, and Implementation Demo

This article explains the three common server‑to‑client push techniques—polling, WebSocket, and SSE—detailing their principles, pros and cons, browser compatibility, and provides step‑by‑step Node.js/Express and plain JavaScript demos to illustrate how to implement SSE in real‑time applications.

Java Captain
Java Captain
Java Captain
Server‑Sent Events (SSE) vs WebSocket vs Polling: Usage Scenarios, Advantages, and Implementation Demo

In many development scenarios the server needs to push data to the client, such as real‑time dashboards, unread messages, or chat functions. This article introduces the usage scenarios of Server‑Sent Events (SSE) and explains how to use SSE.

Implementation schemes for server‑to‑client data push

Polling

WebSocket

SSE

Polling Overview

Polling is a pseudo‑push method where the client repeatedly sends single‑request HTTP calls to the server, creating the illusion of server‑initiated data. It is the least desirable option because each request incurs full HTTP handshake overhead, occupies browser connection slots, and cannot deliver data promptly.

Drawbacks of polling:

Each request requires a new HTTP connection (handshake, teardown), wasting resources.

The client must keep sending requests from page load, which is unfriendly to the client.

Browsers limit concurrent connections per domain (e.g., Chrome limits to 6), and long‑running polls occupy these slots.

Long polling intervals may cause delayed data retrieval.

WebSocket Overview

WebSocket is a bidirectional protocol that allows both client and server to communicate simultaneously. It is powerful but requires the new ws/wss protocol, which may not be supported by all browsers.

Compared with SSE, WebSocket is heavier due to its richer functionality and more complex structure.

SSE Overview

SSE is a unidirectional protocol built on a long‑living HTTP connection, allowing the server to push data to the client but not vice‑versa.

A long‑living connection is an HTTP/1.1 persistent connection that enables multiple requests/responses over a single TCP connection, reducing server load and improving performance.

SSE is lightweight, consumes fewer client resources, and works over standard HTTP, so existing servers support it without extra configuration.

Note: Internet Explorer does not support SSE.

Browser compatibility of SSE:

Differences between WebSocket and SSE

Polling

Polling is only used when both WebSocket and SSE are unsupported, which is extremely rare.

WebSocket vs SSE

Both are common communication solutions; neither is universally better—choice depends on business requirements.

WebSocket is full‑duplex, supporting bidirectional communication; SSE is one‑way, server‑to‑client only.

WebSocket requires server support for the ws protocol; SSE runs on HTTP, supported by all servers.

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

SSE automatically handles reconnection; WebSocket needs extra handling.

SSE allows custom data types.

Business scenarios for each

SSE is ideal for scenarios that only need server‑to‑client push, such as real‑time dashboards or message center notifications.

WebSocket is suitable for bidirectional communication, e.g., chat applications where both sides send messages.

SSE Main APIs

Establish an SSE connection:

var source = new EventSource(url);

SSE connection states

source.readyState

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 related events

open : triggered when the connection is opened.

message : triggered when data is received.

error : triggered on communication errors (e.g., disconnection).

Data format

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

SSE documentation: https://www.w3cschool.cn/nwfchn/wpi3cozt.html

How to implement an SSE link? Demo

The demo uses a plain HTML page for the front end and Node.js with Express for the back end.

Step 1: Create index.html and paste the front‑end demo code.

Step 2: Create index.js in a new folder, paste the back‑end demo code, then run:

npm init          // initialize npm
npm i express    // install Express
node index        // start the server

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

Back‑end code demo (Node.js + Express)

const express = require('express'); // import framework
const app = express();
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 cache for long connection
    'Connection': 'keep-alive' // keep‑alive
  });
  console.log("进入到长连接了");
  // continuously send data
  setInterval(() => {
    console.log("正在持续返回数据中ing");
    const data = {
      message: `Current time is ${new Date().toLocaleTimeString()}`
    };
    res.write(`data: ${JSON.stringify(data)}\n\n`);
  }, 1000);
});
app.listen(port, () => {
  console.log(`项目启动成功-http://localhost:${port}`);
});

Summary

SSE is lighter than WebSocket.

SSE is based on HTTP/HTTPS.

WebSocket uses a new ws/wss protocol.

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

Use WebSocket for bidirectional communication.

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

Polling is the least recommended method due to high resource consumption.

Mini‑programs (WeChat) do not support SSE.

real-timeJavaScriptNode.jsWebSocketExpresspollingSSE
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

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