Under The Hood
frontend nextjs Next.js 13+/15 App Router

Next.js streaming SSR with Suspense

Last updated
Prerequisites:
Next.js App Router basics
React Suspense and async rendering concepts
  • nextjs
  • streaming
  • ssr
  • suspense
  • rendering
  • performance

Read at your depth

The practical view

Wrap slow sections in <Suspense fallback={<Skeleton />}>: export default function Page() { return (<main><Header /><Suspense fallback={<PostSkeleton />}><Posts /></Suspense></main>); }. When the server renders the page, everything outside the boundary streams immediately (including the HTML shell and above-the-fold content), while the suspended part renders when its async data resolves — the fallback shows meanwhile. On the client, hydration is also progressive: the shell hydrates first, and each suspense boundary hydrates when its content arrives. loading.js files are the route-level equivalent that wraps the page in Suspense automatically.

The same idea in other frameworks

react equivalent
// React 18+ <Suspense> in any SSR setup (Remix, RSC,
// custom renderToPipeableStream)

Legacy vs modern

Blocking SSR vs streamed Suspense boundaries

A slow fetch delays the entire HTML response in blocking SSR; streaming serves the shell immediately and each slow section when ready.

before → after
Blocking SSR
export default async function Page() {
  const [posts, comments] = await Promise.all([getPosts(), getComments()]);
  return <Feed posts={posts} comments={comments} />;
}
Streamed suspense
<Suspense fallback={<FeedSkeleton />}>
  <Feed />
</Suspense>

Interview gotchas

Under The Hood — a multi-depth technical interview hub.

Press ⌘ K to search.