Long Polling vs Server-Sent Events vs WebSockets

Real-time communication explained: when to use long polling, SSE, or WebSockets, with practical examples and trade-offs.

Jun 27, 20245 min read

Real-time communication sounds fancy, but the core idea is simple: <strong>how does the server send fresh data to the client without making the user refresh the page?</strong> This matters in products like a <strong>chat app</strong>, <strong>trading app</strong>, <strong>betting app</strong>, <strong>team-based live game or fantasy platform</strong>, and <strong>real-time dashboard</strong>. In all of these, the UI should reflect new information quickly. This article explains three common approaches in simple terms:

  • <strong>Long Polling</strong>
  • <strong>Server-Sent Events (SSE)</strong>
  • <strong>WebSockets</strong>

Why do we need real-time communication?

A normal REST API works like this:

  1. Client sends a request
  2. Server sends a response
  3. Connection ends

That is perfect for many features, like login, profile update, or form submission. But some features need fresh updates continuously:

  • a new message arrives in a chat
  • the stock price changes
  • a live bet odd changes
  • a teammate joins a room
  • dashboard metrics refresh every few seconds

1) Long Polling

Long polling is the easiest real-time pattern to understand because it still feels like regular HTTP.

How it works

  1. Client sends a request to the server asking, &quot;Do you have any update for me?&quot;
  2. If the server has data, it responds immediately.
  3. If not, the server may <strong>wait for a short time</strong> before responding.
  4. After the client receives the response, it sends <strong>another request</strong>.

Example: Long Polling server in Node.js

js
const http = require("http");
const port = 2000;

const server = http.createServer((req, res) => {
  if (req.url === "/poll") {
    setTimeout(() => {
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(
        JSON.stringify({
          message: `Hello at ${new Date().toISOString()}`,
        }),
      );
    }, 5000);
  } else {
    res.writeHead(200, { "Content-Type": "text/plain" });
    res.end("Server is up and running");
  }
});

server.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});

<strong>Best for:</strong> Notifications, basic chat, admin dashboards.

2) Server-Sent Events (SSE)

Server-Sent Events are a neat middle ground.

How it works

  1. Client opens <strong>one HTTP connection</strong>
  2. Server keeps that connection open
  3. Server sends updates whenever new data is available

Example: SSE server in Node.js

js
const http = require("http");
const port = 2001;

const server = http.createServer((req, res) => {
  if (req.url === "/events") {
    res.writeHead(200, {
      "Content-Type": "text/event-stream",
      "Cache-Control": "no-cache",
      Connection: "keep-alive",
    });

    const intervalId = setInterval(() => {
      const eventData = `data: Hello at ${new Date().toISOString()}\n\n`;
      res.write(eventData);
    }, 5000);

    req.on("close", () => {
      clearInterval(intervalId);
    });
  } else {
    res.writeHead(200, { "Content-Type": "text/plain" });
    res.end("Server is up and running");
  }
});

server.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});

<strong>Best for:</strong> Live dashboards, stock ticker, notification feeds.

3) WebSockets

WebSockets are the most interactive option.

How it works

  1. Client connects to the server
  2. A persistent connection is established
  3. Both client and server can send messages at any time

Example: WebSocket server in Node.js

js
const WebSocket = require("ws");
const server = new WebSocket.Server({ port: 2002 });

server.on("connection", (socket) => {
  console.log("Client connected");
  socket.send("Welcome!");
  socket.on("message", (message) => {
    console.log(`Received: ${message}`);
    socket.send(`Echo: ${message}`);
  });
  socket.on("close", () => {
    console.log("Client disconnected");
  });
});

<strong>Best for:</strong> Chat apps, multiplayer games, collaborative tools.

Quick comparison

FeatureLong PollingSSEWebSockets
ConnectionsRepeated HTTPOne HTTPPersistent socket
DirectionBidirectionalServer-&gt;ClientBidirectional
LatencyMediumLowLowest
ComplexityLowLowHigh

Recommendation

<strong>Start with Long Polling</strong>, upgrade as needed. All 3 work well, and the right choice depends on how interactive your product really is.

A simple decision guide

Use long polling when:

  • traffic is low or moderate
  • the feature is simple
  • you want the easiest implementation

Use SSE when:

  • updates mostly flow from server to client
  • you want lower overhead than repeated polling
  • dashboards or live feeds are the main use case

Use WebSockets when:

  • both client and server need to talk often
  • latency matters a lot
  • the product is highly interactive, like chat or live collaboration

Operational things people forget

Real-time communication is not only about protocol choice. Operations matter too.

  • idle timeouts from proxies and load balancers
  • reconnection handling on the client
  • authentication refresh for long-lived connections
  • backpressure when messages arrive too fast

These details often matter more in production than the first code example.

Final takeaway

Long polling, SSE, and WebSockets all solve the same basic problem in different ways. Start with the simplest option that matches the product behavior, and only move to a more complex protocol when the user experience truly needs it.