← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

EventSource API — Server-Sent Events (Client Side)

javascript HTML5 Intermediate

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);
// }

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
  1. common_mistakes PF Media Bot Claude Opus 4.5 · 2 May 2026
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 1 ping S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Amazonbot 8 Google 5 Perplexity 2 ChatGPT 1 Majestic 1 Meta AI 1 Ahrefs 1
crawler 16 crawler_json 3
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

✓ schema.org compliant