C.W.K.
Stream
Lesson 04 of 08 · published

Server-Sent Events (SSE)

~14 min · foundations, sse

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

One-way push, the right way

Server-Sent Events is the modern, standardized form of long polling. The client opens a single HTTP request to a special endpoint; the server responds with Content-Type: text/event-stream and never closes; the connection stays open forever and the server writes data: ...\n\n chunks whenever it has something to say.

Why SSE is underrated

Most teams jump from "I need real time" to WebSocket without considering SSE. But for the dominant real-time use case on the modern web — streaming AI tokens — SSE is the right answer. Every major LLM API (OpenAI, Anthropic, Google) uses SSE for streaming chat completions. The browser EventSource handles reconnection automatically. The protocol is plain HTTP, so every proxy is friendly. The only reason to skip SSE is when you need the client to also push frequently.

How cwkPippa uses SSE

cwkPippa's chat endpoints (Claude, Codex, Gemini, Ollama) all stream over SSE — one HTTP POST per turn, response streams back as data: chunks. WebSocket is reserved for use cases that genuinely need full duplex. The lesson Pippa learned: do not pick WebSocket for streaming AI just because it sounds more impressive.

Code

Browser EventSource — three lines·javascript
const source = new EventSource('/api/stream');

source.onmessage = (e) => {
  const data = JSON.parse(e.data);
  console.log('chunk:', data);
};

source.onerror = () => {
  // Browser will auto-reconnect with backoff.
  console.log('disconnected, will retry');
};
FastAPI SSE endpoint·python
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import asyncio, json

app = FastAPI()

async def event_generator():
    while True:
        data = await get_next_event()  # your source
        # SSE wire format: 'data: <payload>\n\n'
        yield f'data: {json.dumps(data)}\n\n'

@app.get('/api/stream')
async def stream():
    return StreamingResponse(
        event_generator(),
        media_type='text/event-stream',
    )

External links

Exercise

Build the FastAPI SSE endpoint above so that it emits a heartbeat tick ({ ts: ... }) every second. Open a browser tab, paste the EventSource snippet into devtools, and watch ticks arrive in real time. Now close your laptop lid for 30 seconds and reopen — confirm the browser auto-reconnects without you writing a single line of reconnection code.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.