Headline: Streaming an AI response in the Next.js App Router takes one Route Handler that returns a streaming Response and one client hook — the AI SDK's streamText and useChat handle the wire protocol. The hard parts live around that code: proxies that buffer the stream into a single blob, compression that swallows token chunks, refreshes that kill in-flight generations, and abort wiring that decides whether you keep paying for tokens nobody is reading.

Key takeaways

Streaming in the Next.js App Router is a Route Handler returning a streamed Response. The AI SDK's streamText plus toUIMessageStreamResponse() emit an SSE-based message stream, and the useChat hook from @ai-sdk/react consumes it.

Chat UIs do not use the browser EventSource API. EventSource only supports GET requests with no body, so AI chat clients POST with fetch and read the SSE-formatted response through a ReadableStream reader.

A stream that works locally but arrives all at once in production is almost always intermediary buffering — compression middleware, nginx proxy_buffering, or a corporate proxy. Cache-Control: no-transform and X-Accel-Buffering: no fix most cases.