Streaming AI Responses over SSE: Practical Guide
SSE shows answers piece by piece but adds states plain JSON lacks: partial chunks, errors after the start, user cancels. Stream only through Responses API; for chat and messages endpoints send stream:false.
Short answer
SSE shows answers in parts but adds states plain JSON lacks: partial chunk, mid-stream error, user cancel. Stream only where supported.
Reading the byte stream
The beginner mistake is treating a network chunk as an event: one chunk can hold several SSE events or half a line. Accumulate a buffer, decode UTF-8 incrementally, split events on empty lines, keep the tail. Parse data events separately from control markers, completion is its own state.
On user cancel close the reader explicitly and record «cancelled by user», not «error»: different analytics and billing branches. Never treat a TCP break as success — wait for the final event and save the request ID.
- chunks are not events: buffer and split
- cancel is its own state, not an error
- TCP break is not completion
- save the request ID always
Limits, timeouts and cost
Streaming is off for chat completions and messages endpoints — send stream:false there or use Responses API. Set separate connect and read timeouts; a single shared timeout either kills long answers or hangs dead connections.
Streaming does not change the price: same tokens, same formula, different delivery. Usage is finalized when the operation closes, so the total exists even if the user closed the tab mid-stream — reconcile against history, not displayed text.
- streaming only via Responses API
- separate connect and read timeouts
- same tokens, same price
- total exists even after tab close
Pre-production test set
Minimum set before prod: short answer, long answer, slow answer, user cancel, network break, error after the first event. For each record what the user sees and what total lands in usage.
Repeat after a partial answer only with an explicit duplication strategy. Long streaming tasks need heartbeats shorter than the operation, otherwise drops look like slow generation.
- six-case test set before prod
- repeat partial only with dedup strategy
- heartbeats shorter than the operation
Sources and related pages
Next step
Russian version: все статьи на русском.