# Streaming response > A model takes ten seconds to finish a thought, and ten seconds of spinner reads as broken. - Canonical: https://patterns.konigi.com/ai-assistants/streaming-response - Group: Turn and response - Level: implementation - Status: published - Updated: September 12, 2026 - Also called: token streaming, progressive rendering, typewriter effect --- ## Problem Someone asks a question and the model needs thirty seconds to answer it. A spinner held for thirty seconds is indistinguishable from a page that's crashed. The viewer can't tell whether the thing is working, stuck, or already failed, and the only available action is to wait or reload. ## Solution Open a long-lived response and emit the answer in pieces as it's produced. The transport is server-sent events: a single HTTP response with a `text/event-stream` content type that stays open while the server writes named events into it. Anthropic's stream is a fair model of the shape—`message_start`, then a run of `content_block_delta` events each carrying a `text_delta`, then `message_delta` and `message_stop`. The client appends each delta and re-renders. The reason this works isn't that it's faster. End to end it's usually a little slower, because chunked encoding and per-event overhead cost something. It works because it moves the wait. Nielsen's three limits put 0.1 seconds at the threshold of feeling instantaneous, 1 second at the limit of uninterrupted flow, and 10 seconds at the limit of holding attention at all. A thirty-second generation blows through all three. The same generation streamed becomes a one-second wait followed by twenty-nine seconds of reading, and reading isn't waiting. The number that governs the experience is time to first token. Three decisions carry most of the design: 1. **The gap before the first token.** This is the only part that is still a wait, and it needs its own treatment—a caret, a shimmer, a "thinking" line. Once deltas arrive the text itself is the progress indicator. 2. **Incremental markdown.** Text streams a character at a time, but a fenced code block, a table, or a link is only meaningful once closed. Rendering markdown on every delta makes tables reflow and half-written links flash as literal brackets. The usual fix is to render closed blocks and hold open ones as plain text until their delimiter arrives. 3. **Scroll.** Pinning the viewport to the bottom is correct until the reader scrolls up to re-read something. Detach on any upward scroll, then offer an explicit return to the live edge. Screen readers need the opposite of what sighted readers get. An `aria-live` region fed one token at a time either interrupts itself continuously or queues thousands of announcements. Announce the response once on completion, and expose the arrival of the first token and the end of the stream as discrete cues rather than narrating the middle. ## Use when The output is linear prose a person reads top to bottom, and generation runs longer than about a second. This covers nearly every chat answer. ## Don't use when The output is only usable whole. A JSON payload, an image, a table that reflows on every row, or a three-word answer all do better arriving complete. Streaming a structure that rearranges itself as it grows is more agitating than a spinner. ## Trade-offs Streaming publishes the first sentence before the model has written the last one, so a confident wrong opening stays on screen and can't be silently revised. It also makes latency look better than it measures, which quietly rewards teams for optimising the wrong number. Incremental rendering costs real complexity in the markdown layer, and every product that skipped it shipped flickering tables. Auto-scroll is the single most complained-about behaviour in the pattern, and it always comes from someone reading while the answer arrives. ## Checklist - What's the time to first token, and is it measured separately from total generation time? - What fills the gap between send and first token? - Does a half-written code fence, table, or link render as literal markdown while it streams? - When the reader scrolls up mid-stream, does the view stay where they put it? - Is there an obvious way back to the live edge once they have detached? - What does a screen reader hear while three hundred tokens arrive? - If the connection drops at token 200, what stays on screen and what does the viewer see? - Can the viewer copy or act on a partial response before it finishes? - Does the composer stay usable while a response is streaming? - Is the end of the stream marked in a way a person and a screen reader can both detect? ## Compare **ChatGPT** keeps the composer live while a response streams, so a correction can be typed before the answer lands. **Claude** moves long structured output into a side panel rather than the transcript, so a document being generated does not reflow the conversation underneath it. **Perplexity** resolves and shows its sources before the prose begins, so the citations a sentence points at already exist by the time the sentence arrives. **GitHub Copilot** goes the other way for inline code completion and presents a suggestion whole, because ghost text that grows character by character inside an editor is unreadable. ## Related Message turn is the container each streamed answer lands in. Stop generation is the control that only exists because streaming made the middle of a response a place the viewer can stand. Reasoning disclosure streams too, on a separate track and usually collapsed. Artifact panel is where output goes when streaming it into the transcript would wreck the transcript. Generation error is what the pattern owes you when the stream dies halfway. ## Related patterns - [Message turn](https://patterns.konigi.com/ai-assistants/message-turn) — Two voices alternate down one column, and the reader has to know at a glance which one is speaking. - [Stop generation](https://patterns.konigi.com/ai-assistants/stop-generation) — The answer went wrong in its first sentence and the viewer has to sit through the other four hundred words. - [Reasoning disclosure](https://patterns.konigi.com/ai-assistants/reasoning-disclosure) — The model worked for thirty seconds and the viewer wants to know whether it understood the question. - [Artifact panel](https://patterns.konigi.com/ai-assistants/artifact-panel) — The answer is a document or a program, and a chat transcript is the wrong container for either. - [Generation error](https://patterns.konigi.com/ai-assistants/generation-error) — The stream died halfway and left a half-written paragraph on the screen. ## Sources - [MDN, Using server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - [Anthropic, Streaming messages](https://docs.anthropic.com/en/api/messages-streaming) - [Nielsen Norman Group, Response Times, The 3 Important Limits](https://www.nngroup.com/articles/response-times-3-important-limits/) --- Screenshots on patterns.konigi.com are reproduced for commentary and criticism. Product names and marks belong to their owners.