python 55 lines · 9 steps

Server-Sent Events streaming in Flask

A Flask blueprint streams live events to clients over a long-lived HTTP connection using the SSE wire format.

Explained by highlit
1import json
2import time
3import queue
4 
5from flask import Blueprint, Response, request, stream_with_context
6 
7from .services import broker
8 
9sse = Blueprint("sse", __name__)
10 
11 
12def _format_event(data, *, event=None, event_id=None, retry=None):
13 lines = []
14 if event_id is not None:
15 lines.append(f"id: {event_id}")
16 if event is not None:
17 lines.append(f"event: {event}")
18 if retry is not None:
19 lines.append(f"retry: {retry}")
20 payload = json.dumps(data, separators=(",", ":"))
21 for line in payload.splitlines():
22 lines.append(f"data: {line}")
23 return "\n".join(lines) + "\n\n"
24 
25 
26@sse.route("/streams/<channel>")
27def stream(channel):
28 subscriber = broker.subscribe(channel)
29 
30 @stream_with_context
31 def event_stream():
32 yield _format_event({"channel": channel}, event="open", retry=3000)
33 last_ping = time.monotonic()
34 try:
35 while True:
36 try:
37 message = subscriber.get(timeout=1.0)
38 except queue.Empty:
39 if time.monotonic() - last_ping >= 15:
40 yield ": keep-alive\n\n"
41 last_ping = time.monotonic()
42 continue
43 yield _format_event(
44 message["data"],
45 event=message.get("type", "message"),
46 event_id=message["id"],
47 )
48 finally:
49 broker.unsubscribe(channel, subscriber)
50 
51 response = Response(event_stream(), mimetype="text/event-stream")
52 response.headers["Cache-Control"] = "no-cache"
53 response.headers["X-Accel-Buffering"] = "no"
54 response.headers["Connection"] = "keep-alive"
55 return response
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1SSE is just a plain-text format over a long-lived HTTP response — id, event, and data fields separated by newlines.
  2. 2Streaming responses in Flask are generators wrapped with stream_with_context so request state survives across yields.
  3. 3A finally block on the generator is the reliable place to release per-connection resources when a client disconnects.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Server-Sent Events streaming in Flask — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code