Choosing Between Polling, Server‑Sent Events, and WebSockets for Real‑Time Web Applications
This article compares three real‑time communication techniques—long/short polling, WebSockets, and Server‑Sent Events—by explaining their mechanisms, presenting client‑ and server‑side code examples, and discussing their advantages, drawbacks, and suitable use‑cases to help developers select the appropriate method for a dashboard application.
Building real‑time web applications requires sending data from server to client, which can be achieved via client‑initiated polling or server‑initiated push.
The three common approaches are:
Long/short polling (client pull)
WebSockets (server push)
Server‑Sent Events (SSE) (server push)
Example use‑case: a dashboard that streams activity feeds from GitHub, Twitter, etc., needing a suitable method.
1. Polling
Polling periodically requests updates; short polling uses fixed intervals, long polling keeps the request open until data is available. Example client‑side long‑polling code:
/* Client - subscribing to the github events */
subscribe: (callback) => {
const pollUserEvents = () => {
$.ajax({
method: 'GET',
url: 'http://localhost:8080/githubEvents',
success: (data) => {
callback(data) // process the data
},
complete: () => {
pollUserEvents();
},
timeout: 30000
})
}
pollUserEvents()
}Drawbacks include multiple TCP round‑trips, lack of multiplexing, and timeout issues.
2. WebSockets
WebSocket provides a persistent full‑duplex TCP connection. The handshake upgrades an HTTP request to WebSocket. Simple client implementation:
$(function () {
window.WebSocket = window.WebSocket || window.MozWebSocket;
const connection = new WebSocket('ws://localhost:8080/githubEvents');
connection.onopen = function () { /* connection opened */ };
connection.onerror = function (error) { /* handle error */ };
connection.onmessage = function (message) {
try {
const githubEvent = JSON.parse(message.data);
} catch (e) {
console.log('This doesn\'t look like a valid JSON: ' + message.data);
return;
}
// handle incoming message
};
});Node.js server side using express‑ws:
const express = require('express');
const events = require('./events');
const path = require('path');
const app = express();
const port = process.env.PORT || 5001;
const expressWs = require('express-ws')(app);
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '/static/index.html'));
});
app.ws('/', (ws, req) => {
const githubEvent = {}; // sample event
ws.send('message', githubEvent);
});
app.listen(port, () => {
console.log('Listening on', port);
});WebSockets require handling many HTTP‑level concerns manually and do not benefit from HTTP/2 multiplexing.
3. Server‑Sent Events (SSE)
SSE uses a single HTTP connection where the server pushes events to the client via the EventSource API. Simple client code:
const evtSource = new EventSource('/events');
evtSource.addEventListener('event', function(evt) {
const data = JSON.parse(evt.data);
// Use data here
}, false);Node.js server implementation:
// events.js
const EventEmitter = require('eventemitter3');
const emitter = new EventEmitter();
function subscribe(req, res) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive'
});
const heartbeat = setInterval(() => res.write('\n'), 15000);
const onEvent = (data) => {
res.write('retry: 500\n');
res.write(`event: event\n`);
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
emitter.on('event', onEvent);
req.on('close', () => {
clearInterval(heartbeat);
emitter.removeListener('event', onEvent);
});
}
function publish(eventData) {
emitter.emit('event', eventData);
}
module.exports = { subscribe, publish };
// App.js
const express = require('express');
const events = require('./events');
const app = express();
const port = process.env.PORT || 5001;
app.get('/events', cors(), events.subscribe);
app.listen(port, () => {
console.log('Listening on', port);
});SSE offers simpler implementation, automatic HTTP/2 multiplexing, and a single connection per client, making it a strong choice for many real‑time dashboards, though it is limited to unidirectional server‑to‑client streams and may not suit high‑frequency bidirectional scenarios like MMO games.
In summary, after evaluating the trade‑offs, SSE often emerges as the most efficient solution for typical dashboard use‑cases, while WebSockets are preferable when full duplex communication is required.
Architects Research Society
A daily treasure trove for architects, expanding your view and depth. We share enterprise, business, application, data, technology, and security architecture, discuss frameworks, planning, governance, standards, and implementation, and explore emerging styles such as microservices, event‑driven, micro‑frontend, big data, data warehousing, IoT, and AI architecture.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.