AI Streaming Responses
Stream AI completions in real time using Server-Sent Events, async chunk iterators, and readable web streams.
TL;DR
- Enable streaming mode by passing the
stream: truerequest option. - Consume incoming text tokens progressively using
for await...ofloops. - Transmit chunks to browser clients using standard
Server-Sent-Eventsheaders.
SDK Streaming Basics
OpenAI Stream FlagRequest streaming response from OpenAI using async chunk iterator.
const stream = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Count 1-10' }],
stream: true,
});Async Iterator LoopIterate over incoming stream chunks progressively as tokens arrive.
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content ?? '';
process.stdout.write(delta);
}Claude Stream HelperUse Anthropic stream event helper for streamlined text handling.
const stream = client.messages.stream({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 500,
messages: [{ role: 'user', content: 'Hi' }],
}).on('text', (d) => process.stdout.write(d));Server-Sent Events (SSE)
SSE Response HeadersConfigure HTTP response headers for real-time text event streaming.
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
});Event SerializationFormat chunk payloads according to standard EventSource spec.
function writeSSE(res: Response, text: string) {
res.write(`data: ${JSON.stringify({ text })}\n\n`);
}Stream End SentinelEmit termination signal so client closes EventSource connection.
res.write('data: [DONE]\n\n');
res.end();Web Streams And Next.js
ReadableStream PipelineConstruct modern Web API ReadableStream for edge runtimes.
const stream = new ReadableStream({
async start(controller) {
for await (const chunk of aiStream) {
controller.enqueue(encoder.encode(chunk));
}
controller.close();
}
});AI SDK streamTextLeverage Vercel AI SDK to stream text directly to client components.
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
const r = streamText({
model: openai('gpt-4o'),
prompt,
});
return r.toDataStreamResponse();Client Disconnect AbortHalt upstream AI generation immediately when HTTP socket closes.
req.on('close', () => {
abortController.abort();
console.log('Client aborted stream');
});Stream Buffering And State
Full Text AccumulatorBuffer individual deltas into complete string for persistence.
let fullResponse = '';
for await (const chunk of stream) {
const token = chunk.choices[0]?.delta?.content ?? '';
fullResponse += token;
}Throttled UI UpdatesBatch rapid token arrival to prevent front-end render lag.
let pending = '';
setInterval(() => {
if (pending) { updateUI(pending); pending = ''; }
}, 50);Final Usage ExtractionExtract final usage statistics from final stream summary chunk.
const final = await stream.finalMessage();
const inTok = final.usage.input_tokens;
console.log(`Total tokens used: ${inTok}`);Tips
- Render incoming tokens directly into user interface elements to reduce perceived wait times from seconds to under 400 milliseconds via
ReadableStream. - Accumulate streamed chunks into a server-side
fullResponsebuffer to persist the final combined completion message in your database.
Warnings
- Do not parse incomplete JSON tokens during streaming; wait for the complete stream to finish before invoking
JSON.parse. - Ensure server connections are cleaned up when clients disconnect by listening for browser
req.on('close')abort events.
In Practice
Streams model tokens to stdout with typewriter effect while accumulating complete text for persistence.
- Enable stream option on OpenAI chat completions create request.
- Initialize accumulator buffer to store full response string.
- Process each incoming chunk delta and write immediately to output.
- Log total character length once stream closes cleanly.
import OpenAI from 'openai';
const openai = new OpenAI();
async function streamText(prompt: string) {
const stream = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: prompt }],
stream: true,
});
let full = '';
for await (const chunk of stream) {
const d = chunk.choices[0]?.delta?.content ?? '';
full += d;
process.stdout.write(d);
}
return full;
}
await streamText('Write a haiku about coding.');FAQ
Streaming delivers the first token to users in hundreds of milliseconds rather than forcing them to wait 10 to 30 seconds for complete generation. This creates an interactive, conversational user experience.
The server returns an HTTP response with headers Content-Type: text/event-stream and Cache-Control: no-cache. As tokens arrive from the AI provider, the server writes formatted data: {text}\n\n events over the persistent connection.
Pass an AbortSignal into the SDK client request. When the HTTP client disconnects or the user clicks stop, call abort() on the controller to terminate provider streaming and stop token consumption.