Streaming AI Responses Intermediate

Streaming is what makes AI interfaces feel responsive. Instead of waiting seconds for a complete response, users see tokens appear in real time. This lesson covers the streaming protocols, how the AI SDK handles them, and how to build custom streaming logic.

How Streaming Works

AI providers stream responses using one of two protocols:

Protocol How It Works Used By
Server-Sent Events (SSE) Server pushes events over a long-lived HTTP connection OpenAI, Anthropic, most providers
ReadableStream Fetch API streams response body as chunks Custom backends, edge functions

Streaming with useChat (Recommended)

The useChat hook handles streaming automatically:

TypeScript
const { messages, input, handleInputChange, handleSubmit } = useChat({
  api: '/api/chat',
  // The last message in the array updates in real-time as tokens arrive
  // No additional code needed for streaming!
});

Custom Streaming with Fetch

For more control, you can implement streaming manually using the Fetch API:

TypeScript
async function streamAIResponse(prompt: string) {
  const response = await fetch('/api/chat', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ messages: [{ role: 'user', content: prompt }] }),
  });

  const reader = response.body!.getReader();
  const decoder = new TextDecoder();
  let result = '';

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const chunk = decoder.decode(value, { stream: true });
    result += chunk;
    setStreamedText(result); // Update React state
  }
}

Streaming Performance Tips

Performance: When rendering streaming text, avoid re-rendering the entire message list on each token. Use React.memo on message components and only update the currently streaming message. The useChat hook handles this automatically.

Handling Stream Interruption

Users should be able to stop a stream in progress:

TypeScript
const { messages, stop, isLoading } = useChat({ api: '/api/chat' });

// Show a stop button while streaming
{isLoading && (
  <button onClick={stop} className="stop-button">
    Stop generating
  </button>
)}

Streaming Mastered!

You understand how streaming works under the hood. In the next lesson, you will learn to manage AI state across conversations.

Next: State Management →