Question

Long Polling vs SSE vs WebSockets vs Comet in JavaScript

phpwebsocketcometlong-pollingserver-sent-events

Question

I have read several articles, but the ideas are still not completely clear to me.

Could someone explain these technologies in a simple and practical way?

  • Long Polling
  • Server-Sent Events (SSE)
  • WebSockets
  • Comet

One explanation I keep seeing is that the server keeps a connection open and pushes data to the client. How exactly is that connection kept open, and how does the client receive and use the pushed data? A small code example would help.

Also, which of these should I use for a real-time application? I often hear about WebSockets, especially with socket.io in Node.js, but why is that commonly mentioned instead of PHP?

Short Answer

By the end of this page, you will understand what Long Polling, Server-Sent Events (SSE), WebSockets, and Comet are, how they send data from server to browser, and when each approach makes sense. You will also see why the server can "keep a connection open," how the browser receives new data, and why Node.js is often mentioned in real-time discussions even though PHP can also be used in some setups.

Concept

Real-time web communication is about reducing the delay between when something happens on the server and when the browser learns about it.

In classic HTTP, the browser sends a request and the server sends a response. After that, the connection usually ends. This works well for normal web pages, but it is not ideal for things like:

  • chat apps
  • live notifications
  • stock price updates
  • multiplayer games
  • dashboards

To make updates feel instant, several techniques were created.

Long Polling

With long polling, the client sends an HTTP request and the server waits before responding. If there is no new data yet, the server keeps that request open. As soon as new data is available, the server sends the response. Then the client immediately sends another request and waits again.

So it looks like a continuous connection, but it is really a repeated cycle of request -> wait -> response -> new request.

Server-Sent Events (SSE)

SSE is a browser feature built on top of normal HTTP. The client opens a connection to the server, and the server keeps sending text-based event messages over that same response stream.

Important detail:

  • communication is one-way: server -> client
  • great for notifications, feeds, progress updates
  • simpler than WebSockets when the browser does not need to send lots of real-time messages back

WebSockets

WebSockets start with an HTTP request, then upgrade the connection to a special protocol designed for ongoing two-way communication.

After the upgrade:

  • client and server can both send messages at any time
  • the connection stays open until one side closes it
  • lower overhead than repeated HTTP requests
  • ideal for chat, collaborative editing, games, and other truly interactive systems

Comet

Comet is not one single protocol. It is an older umbrella term for techniques that simulate server push in the browser. Long polling is one example of Comet. In older discussions, Comet could also include hidden iframes or streaming tricks used before modern APIs became common.

How is the connection kept open?

The server simply does not finish the response yet.

For example:

  • in long polling, the server delays the response until data is ready
  • in SSE, the server sends headers and keeps writing event data to the response stream
  • in WebSockets, the connection is upgraded and kept alive for message frames in both directions

How does the client get the pushed data?

The browser uses different APIs depending on the technique:

  • Long polling: fetch(), XMLHttpRequest, or similar, then repeat
  • SSE: EventSource
  • WebSockets: WebSocket

The browser runs callback functions when data arrives. Your JavaScript code can then:

  • update the DOM
  • show notifications
  • append chat messages
  • redraw charts
  • store data in app state

Why this matters in real programming

Choosing the wrong transport can make a real-time feature:

  • more complex than needed
  • harder to scale
  • less reliable behind proxies or firewalls
  • more expensive in server resources

A notification feed may only need SSE. A chat app usually needs WebSockets. A compatibility-focused legacy app may still use long polling.

Mental Model

Think of each technique like a different way to receive updates from a restaurant kitchen.

Long Polling

You ask, "Is my order ready?" The staff does not answer right away. They wait until it is ready, then tell you. As soon as you hear the answer, you ask again.

That means you are repeatedly asking, but each question may stay open for a while.

SSE

You sit near a speaker that only the kitchen uses. The kitchen announces updates whenever something changes:

  • "Order started"
  • "Order ready"
  • "Pickup now"

You only listen. You do not talk back through that speaker.

WebSockets

You and the kitchen are on a live phone call. Either side can speak at any time.

That makes it perfect for back-and-forth communication.

Comet

Comet is like the older collection of tricks restaurants used before they had better communication systems. Long polling is one of those tricks.

Take Quiz

Syntax and Examples

Long Polling Example

Client side JavaScript:

async function poll() {
  try {
    const response = await fetch('/poll');
    const data = await response.json();

    console.log('Received:', data);
    document.getElementById('output').textContent = data.message;
  } catch (error) {
    console.error('Polling error:', error);
  } finally {
    poll(); // start waiting again
  }
}

poll();

Server idea:

  • wait until new data exists
  • respond with JSON
  • client immediately opens the next request

SSE Example

Client side JavaScript:

const source = new EventSource('/events');

source.onmessage = function (event) {
  console.log('SSE message:', event.data);
  document.getElementById('output').textContent = event.data;
};

source.onerror = function (error) {
  console.error('SSE error:', error);
};

Server sends data like this over the HTTP response stream:

data: Hello from the server

Each event ends with a blank line.

WebSocket Example

Client side JavaScript:

const socket = new WebSocket('ws://localhost:3000');

socket.onopen = function () {
  console.log('Connected');
  socket.send('Hello server');
};

socket.onmessage = function (event) {
  console.log('From server:', event.data);
  document.getElementById('output').textContent = event.data;
};

socket.onclose = function () {
  console.log('Disconnected');
};

This allows two-way communication.

What the client does with the data

The client usually handles incoming data in an event callback and then updates the UI.

socket.onmessage = function (event) {
  const messageList = document.getElementById('messages');
  const item = document.createElement('li');
  item.textContent = event.data;
  messageList.appendChild(item);
};

So the pushed data is not magical. It is just received by JavaScript and used like any other data.

Step by Step Execution

Trace Example: Long Polling

Client code:

async function poll() {
  const response = await fetch('/poll');
  const data = await response.json();
  console.log(data.message);
  poll();
}

poll();

Server behavior:

  • if no new message exists, keep the request open
  • when a new message appears, return { "message": "New update" }

Step by step

  1. poll() runs for the first time.
  2. The browser sends GET /poll.
  3. The server receives the request.
  4. If no new event is ready, the server waits instead of responding immediately.
  5. A new event happens on the server.
  6. The server sends back JSON like:
{ "message": "New update" }
  1. The browser receives the response.
  2. response.json() parses the JSON.
  3. console.log(data.message) prints New update.
  4. poll() runs again and starts the next waiting request.

Trace Example: SSE

Client code:

const source = new EventSource('/events');

source.onmessage = function (event) {
  console.log(event.data);
};

Step by step

  1. The browser opens a connection to /events.
  2. The server responds with headers for an event stream.
  3. The connection stays open.
  4. Whenever new data is available, the server writes something like:
data: Order shipped

  1. The browser detects a complete SSE event.
  2. source.onmessage runs.
  3. event.data contains Order shipped.

Trace Example: WebSocket

Client code:

const socket = new WebSocket('ws://localhost:3000');

socket.onopen = () => socket.send('ping');
socket.onmessage = (event) => console.log(event.data);

Step by step

  1. The browser starts a WebSocket connection.
  2. The server accepts and upgrades the connection.
  3. onopen runs on the client.
  4. The client sends ping.
  5. The server receives ping and may reply with pong.
  6. onmessage runs with pong.
  7. The same connection remains open for future messages.

Real World Use Cases

Long Polling

Useful when:

  • WebSockets are unavailable
  • older environments need support
  • update frequency is low or moderate
  • implementation simplicity matters more than efficiency

Examples:

  • job status updates
  • simple notification systems
  • admin dashboards with occasional changes

SSE

Useful when:

  • the server mainly sends updates to the browser
  • the client does not need constant two-way messaging
  • you want simple browser support with HTTP semantics

Examples:

  • live news feeds
  • deployment logs
  • progress bars for long-running tasks
  • live monitoring dashboards

WebSockets

Useful when:

  • both client and server must send frequent messages
  • low latency matters
  • you need persistent two-way communication

Examples:

  • chat applications
  • multiplayer games
  • collaborative editors
  • trading platforms
  • live cursor or presence updates

Comet

Useful mostly as historical understanding.

Examples:

  • older real-time web apps before modern browser APIs
  • legacy systems still using long polling or streaming hacks
Take Quiz

Real Codebase Usage

In real projects, developers rarely think only in terms of the protocol. They think in terms of message flow, fallbacks, server limits, and user experience.

Common patterns

Guard clauses for connection state

if (socket.readyState !== WebSocket.OPEN) {
  return;
}

socket.send(JSON.stringify({ type: 'chat_message', text: 'Hello' }));

This avoids sending data before the connection is ready.

Parsing structured messages

Real apps usually send JSON, not raw strings.

socket.onmessage = (event) => {
  const message = JSON.parse(event.data);

  if (message.type === 'notification') {
    showNotification(message.text);
    return;
  }

  if (message.type === 'chat_message') {
    addChatMessage(message.user, message.text);
  }
};

Validation and early returns

function handleIncomingMessage(raw) {
  let message;

  try {
    message = JSON.parse(raw);
  } catch {
    return;
  }

  if (!message.type) {
    return;
  }

  // handle valid message
}

Reconnection logic

Connections can drop. Production apps often reconnect.

function connect() {
  const socket = new WebSocket('ws://localhost:3000');

  socket.onclose = () => {
    setTimeout(connect, 2000);
  };
}

connect();

Socket.io and fallbacks

Libraries like socket.io are popular because they can provide:

  • easier event-based APIs
  • reconnection support
  • rooms/channels
  • fallback transport support in some setups

That is one reason people often mention Node.js and Socket.IO in real-time discussions.

Why Node.js is often mentioned instead of PHP

This is usually about ecosystem and server model, not because PHP is impossible.

Node.js became strongly associated with real-time apps because:

  • JavaScript runs on both client and server
  • event-driven I/O fits many connection-heavy workloads well
  • libraries like socket.io became very popular

PHP can still be used, but traditional PHP setups are often built around short-lived request/response cycles. For modern real-time features in PHP, developers usually rely on:

  • Ratchet
  • Swoole
  • ReactPHP
  • Laravel WebSockets
  • a separate WebSocket server beside the PHP app

So the real answer is not "why not PHP?" It is more like: Node.js became a common default for real-time systems, but PHP can do it with the right tools and architecture.

Common Mistakes

1. Assuming all real-time techniques are the same

They are not.

  • Long polling: repeated HTTP requests
  • SSE: one-way server -> client stream
  • WebSockets: two-way persistent connection
  • Comet: older umbrella term

2. Using WebSockets when SSE is enough

Broken decision pattern:

// Using WebSockets for a simple one-way notification feed

If users only need live notifications from the server, SSE may be simpler.

3. Forgetting to reconnect

Connections can fail.

Broken example:

const source = new EventSource('/events');
// no handling for errors or app state changes

Better:

source.onerror = (error) => {
  console.error('Connection issue', error);
};

4. Sending before the socket is open

Broken code:

const socket = new WebSocket('ws://localhost:3000');
socket.send('hello');

This may fail because the connection is not open yet.

Correct:

socket.onopen = () => {
  socket.send('hello');
};

5. Treating server push as magic

The browser still needs JavaScript code to receive, parse, and display the data.

6. Ignoring server resource usage

Long-held connections consume memory and file descriptors. Real-time features need server planning.

7. Confusing Comet with a specific modern API

Comet is mostly a historical label for older push-style techniques, not a single browser API you call today.

Comparisons

ConceptDirectionTransport StyleBest ForLimitations
Long PollingMostly server -> clientRepeated HTTP requests that waitBasic real-time updates, compatibilityMore overhead, less efficient
SSEServer -> clientSingle long-lived HTTP response streamNotifications, feeds, logsOne-way only
WebSocketsTwo-wayPersistent upgraded socket connectionChat, games, collaborationMore setup and infrastructure complexity
CometUsually server -> clientOlder push techniques like long polling/streamingHistorical/legacy systemsNot a single standard API

SSE vs WebSockets

FeatureSSEWebSockets
Server can push to clientYesYes
Client can push to server anytimeNoYes
Built on plain HTTP response streamYesStarts with HTTP, then upgrades
Good for chat appsUsually noYes
Good for live notificationsYesYes
Simpler to implement for one-way updatesYesNo

Long Polling vs WebSockets

FeatureLong PollingWebSockets
Connection modelRepeated requestsOne persistent connection
OverheadHigherLower after connection setup
Browser compatibilityBroadBroad in modern environments
Real-time qualityGood, but less efficientBetter for high-frequency messaging
Take Quiz

Cheat Sheet

Quick definitions

  • Long Polling: client sends request, server waits, responds when data is ready, client repeats.
  • SSE: browser opens an EventSource; server streams events over HTTP.
  • WebSockets: browser opens a WebSocket; both sides send messages anytime.
  • Comet: older umbrella term for server-push techniques like long polling.

Client APIs

// Long polling
fetch('/poll')

// SSE
const source = new EventSource('/events');

// WebSocket
const socket = new WebSocket('ws://localhost:3000');

When to use what

  • Use Long Polling for compatibility or simpler fallback behavior.
  • Use SSE for one-way live updates.
  • Use WebSockets for true two-way real-time communication.
  • Know Comet mainly as historical terminology.

Key rules

  • Long polling is not the same as a permanent socket.
  • SSE is one-way.
  • WebSockets are two-way.
  • The browser needs JavaScript event handlers to use incoming data.
  • Real-time systems should handle reconnects and errors.

Common browser-side events

source.onmessage = (event) => console.log(event.data);
socket.onopen = () => console.log('open');
socket.onmessage = (event) => console.log(event.data);
socket.onclose = () => console.log('closed');

Edge cases

  • Proxies and load balancers may affect long-lived connections.
  • SSE sends text, often JSON as strings.
  • WebSockets may require extra infrastructure support.
  • PHP can support real-time communication, but traditional PHP hosting often is not designed for long-lived connections.

FAQ

What is the difference between long polling and WebSockets?

Long polling uses repeated HTTP requests that stay open until data is ready. WebSockets use one persistent two-way connection.

Is SSE better than WebSockets?

Not generally. SSE is better when you only need server-to-client updates. WebSockets are better when both sides need to communicate in real time.

Is Comet the same as long polling?

Not exactly. Long polling is one Comet-style technique. Comet is a broader, older term for browser push workarounds.

How does the server keep a connection open?

It simply delays finishing the response, or in the case of WebSockets, keeps the upgraded connection alive for future messages.

Can PHP be used for WebSockets or real-time apps?

Yes, but usually not with the most traditional request-per-page PHP setup. Real-time PHP often uses specialized libraries or separate services.

Why is Node.js often used for real-time apps?

Because its event-driven model and ecosystem made it popular for handling many simultaneous connections efficiently.

Should I use WebSockets for notifications?

Only if you also need two-way communication. If the server just sends updates to the browser, SSE is often simpler.

Do I still need JavaScript on the client?

Yes. The browser receives events, but your JavaScript code must decide what to do with the data.

Take Quiz

Mini Project

Description

Build a tiny live notification demo that shows the difference between one-way and two-way real-time communication. The project uses Server-Sent Events for server-to-client updates because it is a simple and practical way to stream live messages to a browser.

This demonstrates how a server can keep an HTTP response open and push new data as events happen.

Goal

Create a page that receives a new server message every few seconds and displays it live without refreshing the page.

Requirements

  • Create a small Node.js server with an /events endpoint that streams SSE messages.
  • Create an HTML page that connects using EventSource.
  • Show each incoming message in a list on the page.
  • Send a new message from the server every 3 seconds.
  • Handle connection errors in the browser console.
Take Quiz

Keep learning

Related questions

View more