Skip to main content
Streaming allows the server to send parts of a page to the client as soon as they’re ready, rather than waiting for the entire page to render. Users see content sooner, even if parts of the page are still loading.

How streaming works

Without streaming, the browser must wait for the server to render the full page before showing anything. With streaming, Next.js sends a static shell immediately and streams in dynamic content as it resolves:
Streaming is built on HTTP chunked transfer encoding. Each <Suspense> boundary in your component tree becomes a streaming chunk.

Two ways to stream

loading.js

Streams an entire route segment. Wraps page.tsx in a <Suspense> boundary automatically.

React Suspense

Streams specific parts of a page. Gives you granular control over which components stream.

With loading.js

Create a loading.js file in the same folder as your page to show a loading state while the page renders:
On navigation, the user immediately sees the layout and loading state. The new content swaps in once rendering is complete. How it works internally: loading.js is nested inside layout.js and automatically wraps page.js and its children in a <Suspense> boundary.
A layout that accesses uncached or runtime data (such as cookies(), headers(), or uncached fetches) does not fall back to the same route segment’s loading.js. It blocks navigation until the layout finishes rendering. Move data fetching into page.js where loading.js can cover it, or wrap the uncached access in its own <Suspense> boundary.

With <Suspense>

For more granular control, wrap specific components in <Suspense> boundaries:
Content outside the <Suspense> boundary (<header>) is sent immediately. Content inside streams in when the async work completes.

Creating meaningful loading states

Design loading states that help users understand the app is responding. Good fallback UI examples:
  • Skeletons: placeholder shapes that match the layout of the final content
  • Spinners: for simple, short-duration loads
  • Partial content: a cover photo or title before body content loads

Streaming with Server Components

Server Components and <Suspense> work together. An async Server Component inside a <Suspense> boundary streams its content when it resolves:

Streaming data from Server to Client

Pass an unawaited promise from a Server Component to a Client Component, then resolve it with the use API:

Streaming with Partial Prerendering

When Cache Components is enabled, Next.js uses Partial Prerendering (PPR) by default. The static shell (including <Suspense> fallbacks) is prerendered at build time. Dynamic content streams in at request time:
The <Suspense> fallback (<p>Loading preferences...</p>) is included in the static HTML shell sent on the first request. The UserPreferences content streams in once it resolves.