Question
WebSockets vs Server-Sent Events (EventSource): Differences, Use Cases, and When to Choose Each
Question
Both WebSockets and Server-Sent Events (SSE, via EventSource) can push data from a server to a browser. They appear to solve similar problems.
What are the practical differences between WebSockets and Server-Sent Events?
When should you choose one over the other?
Please focus on factual, technical differences such as communication model, protocol behavior, browser support considerations, and common use cases.
Short Answer
By the end of this page, you will understand how WebSockets and Server-Sent Events (SSE) differ, what problem each one solves best, and how to choose the right option for real applications. You will also see simple JavaScript examples, common mistakes, and a small project that demonstrates server-to-browser streaming with SSE.
Concept
WebSockets and Server-Sent Events are both used for real-time communication between a browser and a server, but they are not the same tool.
WebSockets
WebSockets provide a full-duplex connection. That means:
- the client can send messages to the server
- the server can send messages to the client
- both directions can happen over the same long-lived connection
A WebSocket connection begins as an HTTP request and then upgrades to the WebSocket protocol. After that upgrade, communication is no longer normal HTTP request/response.
This makes WebSockets a strong choice for features like:
- chat apps
- multiplayer games
- collaborative editing
- live dashboards where clients also send frequent updates
Server-Sent Events (SSE)
SSE is designed for one-way streaming from server to browser over regular HTTP. The browser opens a connection using EventSource, and the server keeps sending text-based events over time.
With SSE:
- the server can push updates to the browser
- the browser does not send messages back through the same SSE connection
- if the browser needs to send data, it uses normal HTTP requests such as
fetch()or form submissions
SSE is often a good fit for:
- notifications
- live news feeds
- status updates
- log streaming
- progress updates
Why this matters
Choosing the wrong tool can add complexity.
Mental Model
Think of these two technologies like communication channels:
- WebSocket is like a phone call. Both sides can talk at any time.
- SSE is like a radio broadcast. The server keeps talking, and the browser listens.
If your app only needs to listen for updates, a radio broadcast is simpler. If your app needs a conversation, you need the phone call.
Syntax and Examples
WebSocket in JavaScript
const socket = new WebSocket('ws://localhost:3000');
socket.addEventListener('open', () => {
console.log('Connected');
socket.send('Hello server');
});
socket.addEventListener('message', (event) => {
console.log('Received:', event.data);
});
socket.addEventListener('close', () => {
console.log('Connection closed');
});
This creates a persistent two-way connection. The browser can both send and receive messages.
Server-Sent Events in JavaScript
const source = new EventSource('/events');
source.addEventListener('message', (event) => {
.(, event.);
});
source.(, {
.(, error);
});
Step by Step Execution
Consider this SSE example:
const source = new EventSource('/events');
source.onmessage = (event) => {
console.log('Message from server:', event.data);
};
Here is what happens step by step:
-
new EventSource('/events')tells the browser to open an HTTP connection to/events. -
The server responds with headers such as:
Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive -
The server keeps the connection open instead of ending the response.
-
When the server writes:
data: Build completethe browser receives one SSE message.
-
The browser triggers
source.onmessage. -
event.datacontains the stringBuild complete.
Real World Use Cases
Good use cases for SSE
SSE is usually a strong choice when updates only need to flow from the server to the browser:
- Notifications: new alerts, messages, or reminders
- Live logs: deployment logs, job output, monitoring streams
- Status updates: background task progress, queue progress, report generation
- News or price tickers: simple feed-style updates
- Admin dashboards: server health, counts, or activity feeds
Good use cases for WebSockets
WebSockets are better when both sides need to send data frequently or with low latency:
- Chat applications
- Multiplayer games
- Collaborative editors
- Real-time whiteboards
- Trading interfaces where the client also sends actions quickly
- Remote control systems where commands and updates happen continuously
Rule of thumb
- Choose SSE for simple server push.
- Choose WebSocket for interactive two-way communication.
Real Codebase Usage
In real projects, developers usually choose based on communication direction, infrastructure, and simplicity.
Common SSE patterns
- Streaming background job progress
- Pushing notifications after database changes
- Sending log lines to an admin page
- Keeping implementation simple using standard HTTP
A common pattern is:
- Browser opens an
EventSource - Server emits updates as events
- Browser sends user actions back separately with
fetch()
This works well when the app does not need a custom bidirectional protocol.
Common WebSocket patterns
- Message hubs for chat rooms
- Publish/subscribe systems for real-time channels
- Presence tracking such as online/offline users
- Low-latency event handling for collaborative apps
Related codebase patterns
Guard clauses
When handling incoming WebSocket messages, code often validates the message early:
function handleMessage(raw) {
let message;
try {
message = JSON.parse(raw);
} catch {
return;
}
(!message.) ;
}
Common Mistakes
1. Using WebSockets when SSE is enough
If the browser only needs to receive updates, WebSockets may add unnecessary complexity.
Better choice: use SSE for one-way event streams.
2. Expecting SSE to send client messages
This is a very common misunderstanding.
Broken expectation:
const source = new EventSource('/events');
source.send('hello'); // ❌ EventSource does not have send()
EventSource is receive-only.
3. Forgetting the correct SSE response format
Broken SSE output:
Hello client
Correct SSE output:
data: Hello client
The data: field and blank line are important.
4. Assuming WebSockets are just faster HTTP
WebSockets are a different protocol after the upgrade. They are not the same as repeatedly calling fetch().
5. Ignoring reconnection behavior
SSE clients often reconnect automatically. Beginners sometimes forget this and accidentally duplicate state handling.
Comparisons
| Feature | WebSockets | Server-Sent Events (SSE) |
|---|---|---|
| Communication direction | Two-way | Server to client only |
| Protocol | WebSocket protocol after HTTP upgrade | Standard HTTP streaming |
| Browser API | WebSocket | EventSource |
| Client can send messages on same connection | Yes | No |
| Server can push updates | Yes | Yes |
| Message format | Binary or text | Text-based event stream |
| Auto-reconnect support | Usually custom | Typically built in by browser |
| Simplicity | More complex |
Cheat Sheet
Quick decision
- Need server → browser only? Use SSE.
- Need browser ↔ server both ways? Use WebSocket.
WebSocket basics
const socket = new WebSocket('ws://localhost:3000');
socket.send('hello');
socket.onmessage = (event) => console.log(event.data);
- Persistent two-way connection
- Supports text and binary data
- Requires connection upgrade
- Usually needs custom reconnect logic
SSE basics
const source = new EventSource('/events');
source.onmessage = (event) => console.log(event.data);
- One-way server-to-client stream
- Built on HTTP
- Text-based only
- Browser usually handles reconnection automatically
SSE event format
FAQ
What is the main difference between WebSockets and SSE?
WebSockets support two-way communication, while SSE only sends events from the server to the browser.
Is SSE faster than WebSockets?
Not in a universal sense. SSE can be simpler and efficient for one-way updates, while WebSockets are better suited for continuous two-way messaging.
Can Server-Sent Events replace WebSockets?
Only when your app needs server-to-client updates only. If the client must send frequent real-time messages, SSE is not a full replacement.
Can I send data from the browser when using SSE?
Yes, but not through the EventSource connection. You usually send data with fetch() or another HTTP request.
Are WebSockets over HTTP?
A WebSocket connection starts with HTTP, then upgrades to the WebSocket protocol.
Do Server-Sent Events reconnect automatically?
In many cases, yes. Browsers typically try to reconnect automatically when the stream is interrupted.
Should I use SSE for chat applications?
Usually no. Chat needs two-way communication, so WebSockets are generally a better fit.
Is SSE text-only?
Yes, SSE sends text-based event data. If needed, structured data is commonly sent as JSON strings.
Mini Project
Description
Build a small real-time status feed where the browser receives live updates from the server using Server-Sent Events. This demonstrates when SSE is a good fit: the server pushes information continuously, and the browser only needs to listen.
Goal
Create a page that shows a stream of server-generated messages in real time using EventSource.
Requirements
- Create an HTTP endpoint that returns an SSE stream.
- Send a new message from the server every few seconds.
- Create a browser page that connects with
EventSource. - Display each incoming message in a list on the page.
- Handle connection errors in the browser.
Keep learning
Related questions
Allow Only Numeric Input (0-9) in HTML Input Using jQuery
Learn how to allow only digits 0-9 in an HTML input using jQuery, with examples, validation tips, common mistakes, and best practices.
CSS :not() Selector for Excluding a Class or Attribute
Learn how to use the CSS :not() selector to target elements that do not have a specific class or attribute, with examples and common mistakes.
Can HTML Checkboxes Be Readonly? Understanding readonly vs disabled in HTML Forms
Learn why HTML checkboxes do not support readonly, how disabled differs, and practical ways to prevent changes while still submitting values.