EventSource API — Server-Sent Events (Client Side)
Also Known As
EventSource
SSE client
server-sent events JavaScript
event stream
TL;DR
EventSource is the browser API for consuming Server-Sent Events (SSE) — a one-directional server-to-client stream over HTTP that automatically reconnects, ideal for live feeds, notifications, and streaming LLM responses.
Explanation
new EventSource(url) opens a persistent HTTP connection where the server pushes text/event-stream formatted messages. The browser automatically reconnects with exponential backoff if the connection drops, sending the Last-Event-ID header so the server can resume from where it left off. EventSource only supports GET requests and plain text — no binary, no custom headers without a polyfill. For bidirectional communication use WebSockets. For streaming responses from a PHP backend, the server writes 'data: <message>\n\n' and flushes — each double-newline is one event. Named events (event: type\n) allow different listeners. SSE works through proxies better than WebSockets and requires no upgrade handshake.
Common Misconception
✗ EventSource and WebSockets are interchangeable. EventSource is server-to-client only and uses plain HTTP — simpler to deploy, works through proxies, auto-reconnects. WebSockets are bidirectional and require a persistent connection upgrade. Use SSE for push-only feeds; WebSockets when the client also needs to send real-time data.
Why It Matters
EventSource is the simplest way to stream real-time updates from a PHP backend — live order status, streaming AI responses, progress bars for long jobs. It requires no WebSocket server, works through standard HTTP infrastructure, and auto-reconnects without any application code.
Common Mistakes
- Not disabling Nginx output buffering — Nginx buffers upstream responses by default; add 'X-Accel-Buffering: no' header or proxy_buffering off in nginx config.
- Forgetting the double newline to terminate events — each SSE message must end with \n\n; a single \n continues the current event's data.
- Not handling the CORS case — EventSource sends credentials by default only to same-origin; for cross-origin, pass { withCredentials: true } and set appropriate CORS headers.
- Long-lived PHP scripts without max_execution_time override — SSE streams run indefinitely; set set_time_limit(0) at the start of the streaming script.
- Not closing EventSource when navigating away — forgetting to call es.close() leaves connections open on the server; attach cleanup to beforeunload or component unmount.
Code Examples
✗ Vulnerable
// ❌ Polling — inefficient, delayed, hammers the server
setInterval(async () => {
const res = await fetch('/api/notifications');
const data = await res.json();
if (data.length) showNotifications(data);
}, 3000); // New HTTP request every 3 seconds even when nothing changed
✓ Fixed
// ✅ EventSource — persistent connection, server pushes when ready
const es = new EventSource('/api/notifications/stream');
es.onmessage = (event) => {
const notification = JSON.parse(event.data);
showNotification(notification);
};
// Named events — different handlers per event type
es.addEventListener('order-shipped', (event) => {
updateOrderStatus(JSON.parse(event.data));
});
es.onerror = (err) => {
// Browser auto-reconnects — this fires on reconnect attempts too
if (es.readyState === EventSource.CLOSED) {
console.error('SSE connection permanently closed');
}
};
// Close when done (e.g. user navigates away)
window.addEventListener('beforeunload', () => es.close());
// PHP side:
// header('Content-Type: text/event-stream');
// header('Cache-Control: no-cache');
// header('X-Accel-Buffering: no'); // Nginx: disable buffering
// while (true) {
// echo 'data: ' . json_encode(getLatestEvent()) . "\n\n";
// ob_flush(); flush();
// sleep(1);
// }
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
23 Mar 2026
Edited
2 May 2026
Views
24
AI edit
PF Media Bot
Claude Opus 4.5 on common_mistakes · 2 May 2026
Edits history 1 edit
- common_mistakes PF Media Bot Claude Opus 4.5 · 2 May 2026
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Amazonbot 8
Google 5
Perplexity 2
ChatGPT 1
Majestic 1
Meta AI 1
Ahrefs 1
Also referenced
How they use it
crawler 16
crawler_json 3
Related categories
⚡
DEV INTEL
Tools & Severity
⚙ Fix effort: Low
⚡ Quick Fix
For a PHP streaming endpoint, set header('Content-Type: text/event-stream') and echo 'data: ' . $message . "\n\n" with ob_flush() + flush() in a loop. On the client, new EventSource('/stream').onmessage = e => console.log(e.data).
📦 Applies To
javascript HTML5
web