How Server-Sent Events Differ from WebSockets (with Real Examples)

Posted by

Understand the real differences between SSE and WebSockets and learn when to pick the right one for your real-time JavaScript app.


Introduction

Modern users expect everything to happen instantly, chats updating in real time, dashboards refreshing automatically, or stock prices streaming live.

As developers, we reach for two tools to make that happen: Server-Sent Events (SSE) and WebSockets.

They sound similar because both push data from a server to the browser, but under the hood, they work in completely different ways.

In this guide, weโ€™ll go deep into:

  • How SSE and WebSockets actually work
  • Real code examples for each
  • Key performance, scalability, and protocol differences
  • When to use one over the other

Letโ€™s break down the differences like real engineers with working code, not theory.


1. The Goal: Real-Time Communication

The web started as a request-response mode: when a user clicks, the browser asks, the server replies, and the connection closes.

Thatโ€™s fine for static content, but not for live apps that need to stay updated without reloads.

To achieve real-time, we need a way for the server to send data proactively, and thatโ€™s where SSE and WebSockets come in.

Both solve the same problem but with different philosophies.


2. What Are Server-Sent Events (SSE)?

Server-Sent Events use a one-way connection:

  • The browser makes a request.
  • The server keeps it open and continuously streams data back.

This uses the HTTP protocol (no special handshake) and the EventSource API, which every modern browser supports.

Example 1 Real-Time Feed with SSE

Server (Node.js + Express)

import express from 'express';
const app = express();

app.get('/events', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const sendEvent = (msg) => res.write(`data: ${msg}\n\n`);
sendEvent('Connection established.');
const interval = setInterval(() => {
sendEvent(`Server time: ${new Date().toLocaleTimeString()}`);
}, 2000);
req.on('close', () => clearInterval(interval));
});
app.listen(3000, () => console.log('SSE server running on port 3000'));

Client (Browser)

const source = new EventSource('/events');
source.onmessage = (e) => console.log('Update:', e.data);

โœ… Youโ€™ll see updates every 2 seconds, no extra requests.

Itโ€™s perfect for dashboards, progress updates, or notification streams.


How It Works

  1. The browser sends an HTTP GET request.
  2. Server responds with Content-Type: text/event-stream.
  3. The connection remains open.
  4. Server sends messages separated by double newlines (\n\n).
  5. The browserโ€™s EventSource API parses them automatically.

No handshake, no binary frames, no complexity, just simple HTTP streaming.


3. What Are WebSockets?

WebSockets create a full-duplex (two-way) connection over a single TCP socket.
After an initial HTTP handshake, the connection upgrades to the WebSocket protocol, a custom binary protocol outside the HTTP request-response cycle.

This allows both sides to send data at any time.

Example 2 Real-Time Chat with WebSockets

Server (Node.js + ws)

import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 3000 });

wss.on('connection', (socket) => {
console.log('Client connected');
socket.send('Welcome to WebSocket chat!');
socket.on('message', (msg) => {
console.log('Received:', msg);
socket.send(`Echo: ${msg}`);
});
});

Client (Browser)

const socket = new WebSocket('ws://localhost:3000');
socket.onmessage = (e) => console.log('Server:', e.data);
socket.onopen = () => socket.send('Hello Server!');

โœ… Both sides can talk freely.
โœ… Perfect for chat, multiplayer games, or collaborative apps.


How It Works

  1. Client sends an HTTP handshake requesting an upgrade.
  2. Server responds with 101 Switching Protocols.
  3. A persistent TCP connection is created.
  4. Both client and server can send messages anytime.
  5. Data can be binary or text enclosed in WebSocket frames.

This makes WebSockets ideal for high-frequency, interactive communication.


4. The Core Difference


5. Real-World Comparison Through Examples

Scenario 1: Live Dashboard (SSE Wins)

You want to update a dashboard with CPU usage every 5 seconds.

Why SSE?

  • One-way updates only.
  • Simple to implement.
  • Auto-reconnect if the network drops.
// Client
const source = new EventSource('/metrics');
source.onmessage = (e) => updateDashboard(JSON.parse(e.data));

Scenario 2: Chat App (WebSocket Wins)

You need both sides to send messages instantly.

Why WebSockets?

  • Two-way, low-latency communication.
  • Works well with multiple clients.
// Client
const socket = new WebSocket('wss://myapp.com/chat');
socket.onmessage = (e) => showMessage(e.data);
sendButton.onclick = () => socket.send(messageInput.value);

6. Performance and Scalability

SSE

  • Uses standard HTTP โ†’ easy to scale through CDNs or load balancers.
  • Each connection uses a lightweight HTTP stream.
  • Best for apps sending occasional updates.

WebSockets

  • Uses persistent TCP connections โ†’ more memory per user.
  • Excellent for high-frequency events (like multiplayer states).
  • Harder to scale horizontally (requires sticky sessions or brokers like Redis).

Rule of thumb:

SSE is great for many clients, low message frequency.
WebSockets are better for
fewer clients, high message frequency.


7. Handling Reconnection and Errors

SSE (Automatic)

const source = new EventSource('/events');
source.onerror = () => console.log('Connection lost, retrying...');

Browsers automatically retry with exponential backoff.

WebSockets (Manual)

let socket = new WebSocket('wss://myapp.com');
socket.onclose = () => {
setTimeout(() => {
socket = new WebSocket('wss://myapp.com'); // Reconnect manually
}, 3000);
};

Frameworks like Socket.IO handle this automatically for you.


8. Browser and Server Support

Both are widely supported, but SSE doesnโ€™t work on very old browsers.


9. When to Use Each

If your app doesnโ€™t need two-way messaging, SSE is faster to build and easier to maintain.


10. Combining Both

Some advanced systems use both technologies:

  • SSE for server-to-client events (like build logs or alerts).
  • WebSockets for user interactions (like commands or responses).

For example:

  • A stock trading app can use SSE for price updates and WebSockets for buy/sell actions.

Conclusion

Server-Sent Events and WebSockets both bring real-time capability to the web, but they solve slightly different problems.

  • SSE is best for simple, one-way, scalable updates.
  • WebSockets shine in two-way, interactive, low-latency scenarios.

If youโ€™re streaming updates like logs or notifications, start with SSE.
If youโ€™re building chats, games, or collaborative tools, go for WebSockets.

Pro Tip: You can even layer SSE on HTTP/2 for performance gains without extra dependencies.


Call to Action

Which one have you used, SSE or WebSockets?
Share your experience in the comments, and bookmark this guide for your next real-time JavaScript project.

Leave a Reply

Your email address will not be published. Required fields are marked *