← Docs
Recipe

Server-Sent Events

Unidirectional real-time streams from server to client over a single HTTP connection.

Overview

SSE delivers a continuous stream of text/event-stream data. The client opens a persistent connection and the server pushes events as they occur — no polling, no WebSocket handshake overhead. Ideal for live dashboards, log tails, and notification feeds.

Server Implementation

export async function GET() {
  const stream = new ReadableStream({
    start(controller) {
      const encoder = new TextEncoder()
      const interval = setInterval(() => {
        const data = JSON.stringify({ time: Date.now() })
        controller.enqueue(encoder.encode(`data: ${data}\n\n`))
      }, 1000)
      // Cleanup on client disconnect
      request.signal.addEventListener('abort', () => clearInterval(interval))
    }
  })
  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    }
  })
}

Client Consumption

const source = new EventSource('/api/events')
source.onmessage = (e) => {
  const payload = JSON.parse(e.data)
  console.log(payload.time)
}
source.onerror = () => source.close()

Edge Notes

  • • Vercel Edge Functions support SSE with streaming responses.
  • • Keep payloads small — large frames may be buffered.
  • • Use event IDs for reliable reconnection and last-event-id tracking.