Server-Sent Events (SSE)
A one-way stream from server to browser over a normal HTTP connection: the server keeps sending chunks, the page reacts as they land.
See it
What it is
Server-Sent Events is one long-lived HTTP response that never finishes. The server sets 'Content-Type: text/event-stream' and keeps writing small 'data:' chunks; the browser reads them as they land through the built-in EventSource API. Traffic flows one way only, server to client, which is exactly the shape of token-by-token LLM output, live progress bars, deploy logs, and price tickers.
Reach for SSE before WebSocket whenever the client has nothing to say back. It is plain HTTP, so it rides through existing auth, CDNs, and load balancers, and EventSource reconnects on its own. It also sends back the ID of the last event it saw, in a 'Last-Event-ID' header. Replay is the half it does not do for you: missed events only come back if your server keeps a buffer of recent ones and knows how to resume from that ID. Sending occasional user actions over a normal POST while the stream runs alongside is a perfectly good architecture.
Gotcha: buffering proxies will eat your stream and deliver everything at the end in one lump, which looks exactly like a broken feature. Disable response buffering (nginx 'proxy_buffering off', or the 'X-Accel-Buffering: no' header), and note that EventSource cannot send custom headers, which is why many apps hand-roll SSE over fetch with a readable stream instead.
Ask AI for it
Stream this response to the browser with Server-Sent Events instead of waiting for the full result. On the server, respond with 'Content-Type: text/event-stream', 'Cache-Control: no-cache', and 'X-Accel-Buffering: no', then write each chunk as a 'data:' line terminated by a blank line, with named events for progress, error, and done, plus a periodic comment line as a heartbeat. On the client, consume it with EventSource (or fetch with a readable stream if custom auth headers are needed), append chunks as they arrive, close the connection on the done event, and show a reconnecting state if the stream drops.