Recipe
Server-Sent Events
Stream real-time updates from server to browser over a single long-lived HTTP connection.
Overview
SSE is a lightweight push protocol built on standard HTTP. The server holds the connection open and writes text/event-stream frames. The browser consumes them via the native EventSource API — no WebSocket handshake, no custom framing.
When to use it
- One-way server→client data flow
- Progress bars, live logs, notification feeds
- Edge Functions that stream token-by-token
- Anywhere WebSocket is overkill
Minimal server (Node)
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
})
let n = 0
const id = setInterval(() => {
res.write(`data: ${JSON.stringify({ tick: n++ })}\n\n`)
}, 1000)
req.on('close', () => clearInterval(id))Client (browser)
const es = new EventSource('/api/stream')
es.onmessage = (e) => console.log(JSON.parse(e.data))
es.onerror = () => es.close()Vercel Edge caveats
Edge Functions have a maximum duration. For long-lived streams use a regional Serverless Function or a dedicated real-time backend. Always set a heartbeat comment line (: ping) every 15s to keep proxies from closing idle connections.