Lesson 25 +10 XP

Dynamic Route Handlers & Streaming Responses

Dynamic Route Handlers & Streaming Responses

Route Handlers support dynamic parameter extraction (like app/api/posts/[id]/route.ts) as well as real-time response streaming using the Web Streams API.

1. Dynamic Route Parameters

Route Handlers receive a second argument containing route parameters.

// app/api/posts/[id]/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const { id } = await params;

  const post = await fetchPostById(id);

  if (!post) {
    return NextResponse.json({ error: 'Post not found' }, { status: 404 });
  }

  return NextResponse.json(post);
}

2. Streaming Responses with ReadableStream

Route Handlers can stream text or binary data directly to the client using ReadableStream, perfect for AI text generation (LLMs), large data export, or live server events.

// app/api/stream/route.ts
export async function GET() {
  const encoder = new TextEncoder();

  const stream = new ReadableStream({
    async start(controller) {
      controller.enqueue(encoder.encode('Streaming chunk 1...
'));
      await new Promise((r) => setTimeout(r, 1000));

      controller.enqueue(encoder.encode('Streaming chunk 2...
'));
      await new Promise((r) => setTimeout(r, 1000));

      controller.enqueue(encoder.encode('Streaming finished!'));
      controller.close();
    },
  });

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/plain; charset=utf-8',
      'Transfer-Encoding': 'chunked',
    },
  });
}

Static vs Dynamic Route Handler Matrix

ScenarioCache StateOpt-Out Trigger
GET Handler with static URLCachedExport export const dynamic = 'force-dynamic'
GET Handler accessing request.nextUrlDynamicAutomatic (accessing request object)
POST / DELETE / PUT HandlersDynamicAutomatic (non-GET HTTP methods are never cached)
Route Handler using cookies()DynamicAutomatic (accessing dynamic request headers)

TL;DR

  • Dynamic parameters are accessed via the params prop passed as the second argument to Route Handlers.
  • In Next.js 15+, params is a Promise that should be awaited (const { id } = await params).
  • Stream live data back to clients by returning a ReadableStream in a Response object.
  • Non-GET methods (POST, PUT, DELETE) are never cached.