Backend Development 14 min read

Server‑Sent Events (SSE): Concepts, Comparison with Polling and WebSocket, and Practical Implementation Demo

This article explains server‑push scenarios such as real‑time dashboards and chat, compares three implementation methods—polling, WebSocket, and SSE—details the advantages and drawbacks of each, and provides step‑by‑step Node.js and frontend demos for using SSE in web applications.

Architect
Architect
Architect
Server‑Sent Events (SSE): Concepts, Comparison with Polling and WebSocket, and Practical Implementation Demo

In everyday development we often encounter scenarios where the server must actively push data to the client, such as real‑time dashboards, unread‑message notifications, and chat functions. This article introduces the usage scenarios of Server‑Sent Events (SSE) and demonstrates 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 HTTP requests to the server, creating a new connection each time. It consumes unnecessary resources, occupies browser concurrent request slots, and cannot guarantee timely data delivery.

Each request requires a full HTTP handshake, causing unnecessary overhead.

The client must keep sending requests for the entire page lifetime, which is unfriendly to the browser.

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

Long polling may still fail to obtain data promptly.

WebSocket overview

WebSocket is a full‑duplex protocol that allows bidirectional communication between client and server. It is powerful but requires the server to support the ws/wss protocol, and not all browsers may support it.

Compared with SSE, WebSocket is heavier because of its richer features and more complex structure.

Browser compatibility of WebSocket

SSE overview

SSE is a unidirectional, long‑living HTTP/1.1 connection that allows the server to push data to the client, but the client cannot send messages back through the same channel.

Long connections are a persistent HTTP/1.1 technique that reduces server load and improves performance.

Advantages of SSE:

Lightweight protocol with lower client overhead compared to WebSocket.

Uses standard HTTP, so existing servers support it without extra configuration.

Note: Internet Explorer does not support SSE.

SSE browser compatibility

Differences between WebSocket and SSE

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

WebSocket requires server support for a new protocol; SSE works over existing HTTP.

SSE is simpler and lighter; WebSocket is more complex.

SSE automatically handles reconnection; WebSocket needs extra handling.

SSE can customize data types.

Suitable business scenarios

If only the server needs to push data (e.g., real‑time dashboards, message center), SSE is the preferred choice.

If bidirectional communication is required (e.g., chat), WebSocket is more appropriate.

SSE main APIs

Creating an SSE connection:

var source = new EventSource(url);

SSE connection states

0 – EventSource.CONNECTING : connection not yet established or disconnected.

1 – EventSource.OPEN : connection established and 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.

Data format

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

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

Demo: How to implement an SSE link

Frontend (plain HTML) 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");
    }
    // open event
    source.onopen = function(event) {
      console.log(source.readyState);
      console.log("长连接打开");
    };
    // message event
    source.onmessage = function(event) {
      console.log(JSON.parse(event.data));
      console.log("收到长连接信息");
      let li = createLi(JSON.parse(event.data));
      document.getElementById("ul").appendChild(li);
    };
    // error event
    source.onerror = function(event) {
      console.log(source.readyState);
      console.log("长连接中断");
    };
  </script>
</body>
</html>

Backend (Node.js + Express) demo:

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(() => {
    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}`);
});

Run the backend:

npm init          // 初始化 npm
npm i express    // 下载 express 框架
node index       // 启动服务

Result screenshot:

Summary

SSE is lighter than WebSocket.

SSE is based on HTTP/HTTPS, so existing servers support it.

WebSocket uses a new ws/wss protocol.

If only server‑to‑client push is needed, use SSE.

If bidirectional communication is required, choose WebSocket.

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

Polling is the last resort due to high resource consumption.

Mini‑programs do not support SSE.

For further reading, see the linked articles at the end of the original post.

backendFrontendNode.jsWebSocketExpressServer-Sent EventspollingSSE
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

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.