lesson depth
Mastery
not started · 0%

Server-Sent Events with FastAPI EventSourceResponse

Implementing reliable Server-Sent Events subscriptions in React components using native EventSource or custom headers fetch.

Freshness: current12 min readAI User Experience and Human-AI Interaction

Mental model

Server-Sent Events (SSE) establish a persistent, one-way push channel from the server to the browser over standard HTTP. Unlike general streams which transmit raw byte chunks, SSE structures the stream into distinct, event-labeled data packets. The browser's native EventSource API handles socket connections and stream parsing automatically, letting React components subscribe to structured event notifications.

Instantiate EventSource
Establish HTTP connection
Server pushes event packets
Trigger message callback
Append event to state
Conceptual teaching model synthesized from:Server-Sent Events - W3C Recommendationsse-starlette python module source repository

Theory

The SSE protocol requires the server to output content with the text/event-stream media type. Individual messages are formatted as line-separated keys, terminated by double carriage returns (\n\n):

text(6 lines)
1event: token
2data: {"text": "hello"}
3
4event: token
5data: {"text": "world"}

In FastAPI, you use starlette's EventSourceResponse to stream structured dicts as formatted events:

python(20 lines)
1# FastAPI Backend
2from fastapi import FastAPI
3from sse_starlette.sse import EventSourceResponse
4import asyncio
5
6app = FastAPI()
7
8async def event_publisher():
9 for token in ["Hello", " ", "World"]:
10 # Yield dict representing SSE fields
11 yield {
12 "event": "message",
13 "data": token
14 }
15 await asyncio.sleep(0.1)
16
17@app.get("/stream-sse")
18async def sse_endpoint():
19 return EventSourceResponse(event_publisher())

In React, you can subscribe using the native EventSource API. It fires listeners automatically and manages automatic connection retries if the network drops:

typescript(24 lines)
1// React Component
2import { useEffect, useState } from "react";
3
4export function SseListener() {
5 const [messages, setMessages] = useState<string[]>([]);
6
7 useEffect(() => {
8 // Note: Native EventSource does not support POST requests or custom auth headers
9 const eventSource = new EventSource("/stream-sse");
10
11 eventSource.onmessage = (event) => {
12 setMessages((prev) => [...prev, event.data]);
13 };
14
15 eventSource.onerror = (err) => {
16 console.error("SSE connection failed:", err);
17 };
18
19 return () => {
20 eventSource.close();
21 };
22 }, []);
23}

Alternatives and trade-offs

  • Native EventSource: Handled by the browser runtime, automatically reconnects, but limited to GET requests and cannot carry custom headers (like Authorization: Bearer <token>).
  • Fetch ReadableStream: Supports POST requests and custom headers, but requires you to write manual string chunking and reconnection loops.
  • WebSockets: Supports bi-directional, full-duplex communication, but carries socket negotiation overhead and bypasses standard HTTP tools like compression and edge CDN caching.

Failure modes and misconceptions

  • Proxy Connection Limits: HTTP/1.1 connections limit SSE channels to 6 concurrent streams per domain. If a user opens multiple tabs, connections will freeze. Always enforce HTTP/2 or HTTP/3 where stream multiplexing bypasses this limit.
  • Custom Header Limitations: Since native EventSource doesn't support custom headers, developers often pass JWT auth tokens as query string parameters (e.g. /stream-sse?token=xyz). If security rules prohibit query parameters in server logs, use a custom fetch wrapper (like @microsoft/fetch-event-source) instead.

Knowledge check

Reflect before revealing the guide

What is the concurrent connection limit for EventSource streams under HTTP/1.1?

Decision scenario

If you are developing a real-time notification panel that only receives updates and uses HTTP/2, use native EventSource for built-in automatic reconnects. If you are feeding a chat client that requires token-authenticated POST parameters for prompt context, bypass native EventSource and write a custom streaming reader using fetch.

Learning outcomes

  • Explain Server-Sent Events with FastAPI EventSourceResponse as a system mechanism rather than a slogan.
  • Compare its alternatives, trade-offs, and production failure modes.
  • Apply the concept to a decision and identify evidence that would validate it.

Trade-offs

Using Server-Sent Events with FastAPI EventSourceResponse can improve capability or control, but it also introduces cost, latency, complexity, and failure modes that must be measured against an explicit objective.

Prerequisites & Related Concepts (2)

Private notes

0 words
Next