Backend Development 14 min read

Server Push Techniques: SSE, WebSocket, and Polling – Usage, Comparison, and Demo

This article explains the three common server‑to‑client push methods—polling, WebSocket, and Server‑Sent Events (SSE)—detailing their principles, advantages, drawbacks, browser compatibility, and provides step‑by‑step demo code for both frontend and Node.js backend implementation.

Top Architect
Top Architect
Top Architect
Server Push Techniques: SSE, WebSocket, and Polling – Usage, Comparison, and Demo

In many web applications, the server needs to push data to the client in real time, such as dashboards, unread messages, or chat features. The article introduces three typical solutions: polling, WebSocket, and Server‑Sent Events (SSE), and explains when to use each.

Polling is the earliest approach where the client repeatedly sends HTTP requests to simulate push. It consumes extra connections, occupies browser concurrency limits, and can be inefficient, making it the least preferred method.

WebSocket provides a full‑duplex communication channel over the ws/wss protocol. It supports bidirectional messaging and is powerful, but requires server support for the new protocol and is comparatively heavier.

SSE is a one‑way, lightweight protocol built on standard HTTP/HTTPS. It keeps a long‑living connection, allowing the server to push events to the browser with low overhead. However, it is not supported by IE and mini‑programs.

The article compares the two protocols:

WebSocket: full‑duplex, stronger features, needs ws support.

SSE: one‑way, lightweight, works on existing HTTP servers.

Both have good browser compatibility, but SSE cannot send data from client to server.

SSE API Overview

Creating a connection: var source = new EventSource(url);

Connection states (source.readyState): 0 = CONNECTING, 1 = OPEN, 2 = CLOSED.

Key events:

open – triggered when the connection is established.

message – triggered when data arrives.

error – triggered on communication errors.

Typical response headers for SSE:

Content-Type: text/event-stream // data format
Cache-Control: no-cache       // prevent caching
Connection: keep-alive       // keep the long connection

Demo Implementation

Frontend (plain HTML/JS):

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

Backend (Node.js + Express):

const express = require('express');
const app = express();
const port = 8088;

// CORS setup
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('Entered long‑connection');
  setInterval(() => {
    const data = { message: `Current time is ${new Date().toLocaleTimeString()}` };
    res.write(`data: ${JSON.stringify(data)}\n\n`);
  }, 1000);
});

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

Running the two files (npm init, npm i express, node index.js) starts the SSE server, and opening the HTML page displays a continuously updating list of timestamps.

Conclusion

SSE is lighter than WebSocket and works over standard HTTP.

Use SSE for one‑way server push scenarios such as dashboards or notification centers.

Choose WebSocket when bidirectional communication (e.g., chat) is required.

Polling should be avoided except for extreme compatibility cases.

Note that IE and mini‑programs do not support SSE.

Node.jsWebSocketExpressServer-Sent EventspollingSSE
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.