Streaming lets Next.js send a page's HTML to the browser in pieces, as each piece becomes ready, instead of waiting for every single data source to resolve before sending anything. This lesson explains how it works and how to use it deliberately.
Sending HTML Progressively, Not All at Once
Without streaming, a dynamically-rendered page must wait for every Server Component's data to resolve before the server sends any HTML at all — one slow data source blocks the entire response. Streaming, powered by React <Suspense>, lets Next.js send the parts of the page that are ready immediately, then stream in additional HTML (plus a small script to slot it into place) as slower parts finish.
loading.tsx (covered earlier) is actually a specific application of streaming — Next.js wraps the whole page's page.tsx in a <Suspense> boundary automatically. This lesson focuses on adding your own, more granular <Suspense> boundaries around individual components.
import { Suspense } from "react";
export default function DashboardPage() {
return (
<>
<h1>Dashboard</h1> {/* renders immediately */}
<Suspense fallback={<p>Loading revenue...</p>}>
<RevenueChart /> {/* streams in once ready */}
</Suspense>
<Suspense fallback={<p>Loading orders...</p>}>
<RecentOrders /> {/* streams in independently */}
</Suspense>
</>
);
}
The heading appears instantly; RevenueChart and RecentOrders each stream in independently, whichever finishes first.
Any async Server Component wrapped in <Suspense> can suspend the boundary while it loads.
The fallback prop is shown instantly, then swapped for the real content once ready.
Multiple <Suspense> boundaries on the same page stream independently of each other.
Streaming requires a dynamic (or partially dynamic) response — fully static pages have nothing to stream.
Streaming Cheat Sheet
Where streaming applies automatically vs. manually.
Mechanism
Scope
loading.tsx
Automatic Suspense boundary for an entire route
Manual <Suspense>
Granular boundary around one specific component
Multiple <Suspense> boundaries
Each streams independently, in any order they resolve
Underlying mechanism
React Server Components + Suspense + HTTP streaming
Why Streaming Improves Perceived Performance
Streaming doesn't necessarily make the total time-to-fully-loaded any faster — the slow data source still takes just as long. What it improves is perceived performance: users see meaningful content (navigation, headings, fast sections) immediately, rather than staring at a blank page while everything loads together.
Choosing Where to Add Suspense Boundaries
A good rule of thumb is to wrap exactly the components whose data sources are meaningfully slower than the rest of the page — wrapping every single component individually adds unnecessary complexity without a proportional UX benefit.
Not designing a fallback that visually resembles the real content, causing jarring layout shifts when it swaps in.
Key Takeaways
Streaming sends a page's HTML progressively, as each part becomes ready, instead of all at once.
React <Suspense> boundaries define which parts of the page can stream independently.
loading.tsx is an automatic, whole-route application of the same underlying mechanism.
Streaming improves perceived performance even when total load time is unchanged.
Add Suspense boundaries deliberately around genuinely slow sections, not everywhere.
Pro Tip
Design fallback skeletons that match the real content's approximate size and layout — a fallback that's a different height than the actual content causes a visible layout shift the moment the real content streams in, which undermines the smooth feel streaming is supposed to provide.
You've completed the rendering deep dive. Next, move into styling — how to apply CSS, CSS Modules, Tailwind, and Sass in a Next.js project.