API Styles Deep Dive · 5 of 7

Server-Sent Events — One-Way Streams over HTTP

Server-Sent Events (SSE) is a standard HTTP response that just… never ends. The server keeps writing data: lines; the browser's EventSource API reads them. It's the simplest way to push from server to client, it survives corporate proxies in ways WebSockets don't, and it's what powers the streaming output of every modern AI chat product.

HTTPOne-WayEventSourceAuto-ReconnectAI Streaming
← Back to APIs & Networking
Quick Facts

What SSE Is

Basic Concepts

  • Standardized: part of the HTML5 spec. Native EventSource in every browser.
  • Just HTTP: a normal response with Content-Type: text/event-stream that doesn't end. No protocol upgrade, no special framing.
  • Format: plain text. Each event is one or more lines like data: {"foo":1}, separated by a blank line.
  • One-way: server → client only. The client uses regular REST calls to talk back.
  • Auto-reconnect built in. If the connection drops, the browser reconnects automatically and sends Last-Event-ID so the server can resume.
  • Works with HTTP/2 and HTTP/3 — modern multiplexing means many SSE streams over one connection without exhausting browser limits.
Why It Wins

What You Buy

Radically Simple

The server writes lines; the client reads lines. No framing protocol. No Upgrade handshake. No subprotocol negotiation. A working SSE server is ten lines of Express, FastAPI, or Spring code.

id: 42
event: message
data: {"role":"assistant","content":"Hello"}

id: 43
data: {"role":"assistant","content":"!"}
Survives Proxies and Firewalls

It's an ordinary HTTP response. Every proxy, every CDN, every corporate firewall already understands it. Compare with WebSockets, where one corporate proxy that doesn't pass Upgrade headers cleanly takes down the whole feature.

Free Reconnection and Resume

The browser handles reconnect automatically. The server's optional id: field becomes a resume cursor — on reconnect the browser sends Last-Event-ID, and the server can pick up where it left off. None of this requires application-level code.

Plays Nicely with Auth

Standard cookies, bearer tokens, and CORS preflights work — it's just HTTP. Compare with WebSockets, where the browser's API blocks custom headers and you end up with query-string tokens or short-lived tickets.

Where It Hurts

Real Constraints

One-Way Only

The server can push but the client can't push back over the same connection. Use a regular POST for client-to-server messages. For most use cases this is a non-issue (and arguably cleaner — separate the concerns), but if you really need symmetric push, WebSockets win.

UTF-8 Text Only

SSE is a text protocol. Binary payloads need base64 — fine for small things, wasteful for large ones. If you're streaming raw audio or video frames, look elsewhere (WebSockets, WebRTC, gRPC streaming).

Connection Limits on HTTP/1.1

Browsers limit connections per host (typically 6 on HTTP/1.1). Each SSE stream burns one of those slots. Open six streams and other requests stall. Mitigation: use HTTP/2 (no per-host limit), or fan multiple logical streams through one SSE connection with an event channel.

Server Resource Use

Long-lived connections are still long-lived. Per-connection memory, file descriptors, and worker slots add up. Plan capacity by concurrent connections, not by RPS. Use async runtimes (Node, Go, async Python, Spring WebFlux) — thread-per-connection servers fall over fast.

Some Proxies Buffer

NGINX with the wrong config will buffer the entire response and defeat streaming. Set X-Accel-Buffering: no, ensure proxy_buffering off for the location, and disable response compression on the stream (gzip off for SSE responses).

Use Cases

Where SSE Shines

  • AI token streaming — every modern LLM-backed product (ChatGPT, Claude.ai, Copilot) ships tokens to the browser via SSE.
  • Notifications and toasts — order status, "someone mentioned you", deploy completed.
  • Live dashboards — metrics, leaderboards, build pipelines.
  • Log tailing — follow logs from a server in the browser.
  • Progress feedback — long-running jobs that report incremental progress.
  • GraphQL subscriptions over SSE (graphql-sse) — an alternative to WebSockets for real-time GraphQL.
Decision

SSE vs WebSockets vs Polling

NeedPick
Server pushes occasional updates; client uses normal REST to actSSE. Simpler than WebSockets and just as effective.
Both sides push frequently and tiny payloadsWebSockets. Lower per-message overhead, true full-duplex.
Pushes are infrequent (minutes apart) and clients can tolerate delayPolling or long-polling. Don't over-engineer.
Streaming AI completionsSSE. Industry default for a reason.
Binary streams (audio, video)WebSockets, WebRTC, or HLS, not SSE.
Continue

Other API Styles