top of page

Server-Sent Events

  • Writer: Pradeep P
    Pradeep P
  • 3 days ago
  • 3 min read

Layer 2 · Post 9 of 10

← Previous: WebSockets → Next: Webhooks

Layer 2 — Communication · Post 24 of 88

Server-Sent Events stream updates from server to browser over a simple HTTP connection. One direction, low ceremony, good enough for many live UIs.

What you'll learn

  • How SSE differs from WebSockets and from polling

  • The text/event-stream format and last-event-id resume

  • Why LLM token streaming often looks like SSE

The idea in one minute

Server-Sent Events (SSE) is HTTP where the server keeps the response open and writes data: ... lines as things happen. The browser EventSource API reconnects for you.

It is one-way: server → client. The client still uses normal HTTP for sends.

That is enough for live scores, feed ticks, job progress, and streaming LLM tokens (Layer 6). You skip WebSocket handshake, custom ping protocols, and binary frames.

Why it matters

Not every live UI is a chat. Many products only need "tell me when this changes." SSE fits HTTP/1.1 and HTTP/2, plays nicer with some proxies than WebSockets, and is trivial to demo: curl the stream.

Limits: typically no binary, no client→server on the same socket, and some older proxies buffer the stream (you need X-Accel-Buffering: no style headers). Browsers cap concurrent SSE per domain (HTTP/1.1). HTTP/2 multiplexing helps.

How it works

Response headers: Content-Type: text/event-stream, no buffering, keep-alive.

Body:

id: 17 event: progress data: {"percent": 40}

data: hello world

Blank line ends an event. EventSource fires onmessage or named events.

If the connection drops, the browser reconnects and sends Last-Event-ID. Your server can resume from that id if you stored a log. That is the cheap version of "don't miss ticks."

Compared to WebSockets

  • : Direction; SSE: server → client; WebSocket: both

  • : API; SSE: EventSource; WebSocket: lower-level

  • : Protocol; SSE: HTTP; WebSocket: upgraded TCP frames

  • : Typical use; SSE: notifications, streams; WebSocket: chat, games, collab

You can mix: REST POST to send, SSE to listen.

A simple example

"Export CSV" job:

  • POST /exports → { "jobId": "abc" }

  • GET /exports/abc/events as SSE: queued → running → done with a download URL

  • The page never polls. If the user refreshes, Last-Event-ID or a GET of job status recovers.

LLM chat: POST /complete returns text/event-stream of tokens. Same idea, different payload.

Common mistakes

Buffering at nginx / CDN. The user sees nothing until the buffer fills. Disable proxy buffering for that route. CDNs may not be the right place for long streams.

No heartbeat. Intermediate timeouts close quiet streams. Send a comment line : ping every N seconds.

Using SSE for high-frequency binary. Use WebSockets or a dedicated protocol.

Forgetting auth on the GET. EventSource cannot set custom headers in the oldest browsers; people stuff tokens in query strings. Prefer cookie auth or a fetch-based SSE client.

How this shows up in real systems

  • OpenAI-style chat UIs: SSE or chunked HTTP for tokens.

  • GitHub / Twitter (historically): live comment/event streams.

  • Kubernetes kubectl logs -f: similar streaming, not always SSE.

Recap

  • SSE is one-way live HTTP. Simple, enough for many UIs.

  • Resume with event ids. Don't let proxies buffer.

  • Use WebSockets when the client must push continuously on the same connection.

The last common "call me when something happens" pattern is not a live socket at all. It is a webhook.

Layer 2 · Post 9 of 10

← Previous: WebSockets → Next: Webhooks

Comments


About Me

DSC_7604.jpg

Hi, I am a software engineer from Bangalore, India. Love spending time on gaming and photography. This website is where I will ocassionally throw what comes to my mind. Hope it is useful or at least entertaining to you. :)

 

  • Instagram
  • Facebook
  • Twitter
  • LinkedIn
  • YouTube
  • 500px

© 2023 by Going Places. Proudly created with Wix.com

bottom of page