After this topic
You will be able to explain why ChatGPT types instead of spinning — and why that is not a UI trick. You will know which latency number users feel, which number you pay for, and when waiting is still the right call.
The spinner is lying
You already know generateText. Streaming is the same call — same model, same messages — but the UI updates on every token instead of once at the end.
A chat that blocks until the full reply is ready feels broken, even when the model is fast. The user sent a message. They are looking at a spinner. Meanwhile the model may already have the first sentence. You are hiding progress that already exists.
Streaming sends each token to the browser as the model produces it — the same pattern every consumer chat product uses. Total time can be similar. Perceived time is not. A 4-second wait with words at 400ms feels faster than a 3-second wait with a spinner, because the first number is “the product is working” and the second is “is it stuck?”
This only works because of Day 1: the model cannot skip to the end of the paragraph. Token two does not exist until token one is chosen. You might as well show them in that order.
What actually moves
On the server you call streamText instead of generateText. The AI SDK opens a stream from the provider (or Gateway), and you turn that into an HTTP response the client hook knows how to read.
On the client, useChat from @ai-sdk/react holds the messages array and appends tokens as they arrive. You do not parse Server-Sent Events yourself. You do not put the API key in this file.
The messages you send are the same array as yesterday. Streaming is delivery, not a different mental model. Tool calls, later, ride the same stream as extra parts on the assistant message.
- Server — streamText → toUIMessageStreamResponse()
- Wire — Server-Sent Events (chunks of UI messages, not a finished JSON blob)
- Client — useChat + DefaultChatTransport({ api: '/api/chat' })
- Same getModel() as generateText. Same messages array. History still lives where you stored it.
What “fast” actually means
Two clocks matter. Time-to-first-token (TTFT) is how long until the first word paints. That is the clock users feel. Time-to-last-token is how long until the model stops. That is closer to what you pay for, plus a bit of network.
A bigger model is often slower to first token and better at hard instructions. A smaller model is snappier and enough for short copy. Streaming does not make a slow model cheap. It makes a slow model honest: the user sees work happening.
If the first token takes two seconds, look at cold starts, the route’s region, and whether you stuffed a huge system prompt. Streaming will not hide a 2,000-token preamble.
When not to stream
Scripts, cron jobs, and tests should wait. A stream is harder to assert on. Classification and “extract this object” should wait (or use structured output) so you never render a half-field.
If the answer is one word, streaming buys you nothing. If the answer is a page, it is the difference between a product and a spinner.
You also cannot easily “undo” a streamed sentence the user already read. If you must validate the whole answer before showing it (moderation, a schema), wait, then render once. Streaming is a contract with the user: what they see is the answer, as it is born.
Related patterns
Docs
Official API reference for this chapter.
Common questions
- Why streaming beats waiting?
- Users perceive speed when tokens arrive incrementally — even if total latency is similar.
- What will I be able to do after this lesson?
- You will be able to explain why ChatGPT types instead of spinning — and why that is not a UI trick. You will know which latency number users feel, which number you pay for, and when waiting is still the right call.
- How long does this lesson take?
- About 16 minutes of reading. It is a free chapter in the AI SDK Patterns TypeScript course.
- When should I not use this?
- Scripts, cron jobs, and tests should wait. A stream is harder to assert on. Classification and “extract this object” should wait (or use structured output) so you never render a half-field.
Written by Akash Panchal·Updated August 29, 2026