Streaming & Suspense
Master streaming in Next.js — how Suspense enables progressive HTML delivery, skeleton UIs, and parallel data loading for dramatically faster perceived performance.
Last reviewed: January 2025
🔍 What Is It?
Streaming in Next.js uses HTTP streaming + React Suspense to send HTML progressively:
- →The page shell (layout, fast content) is sent immediately
- →Slow sections (database queries, external APIs) stream in as they complete
- →Each Suspense boundary is an independent streaming unit
- →Users see and interact with fast content while slow content loads
Without streaming: User waits 2 seconds for ALL data before seeing ANY content.
With streaming: User sees the page shell in 100ms, fast sections in 200ms, slow sections in 2 seconds.
🎯 Why Do We Need It?
Traditional SSR blocks on the slowest data fetch. A page with 5 data fetches waits for all 5 before sending any HTML.
Streaming eliminates this:
- →Faster Time to First Byte (TTFB) — page shell sent immediately
- →Better perceived performance — users see content progressively
- →Parallel data loading — independent sections load simultaneously
- →Better UX — skeleton loaders instead of blank pages
🏗️ What Happens in Real Projects?
Streaming in a dashboard:
- →Page shell (header, sidebar, layout) — instant, 0ms
- →User greeting — 50ms (fast session lookup)
- →Recent activity — 150ms (simple DB query)
- →Revenue chart — 800ms (complex aggregation)
- →AI insights — 2000ms (LLM API call)
With Suspense, all five load in parallel and stream in as ready. Without Suspense, the user waits 2000ms for everything.
⚙️ How It Works
Streaming rendering pipeline:
- Request arrives
- Next.js renders the page tree synchronously until it hits a Suspense boundary
- Sends the outer HTML (layout, fast content) to the browser immediately
- Browser displays the page shell + skeleton fallbacks
- Async Server Components inside Suspense boundaries continue rendering
- As each completes, Next.js streams the HTML chunk to the browser
- Browser replaces the skeleton with the real content (no JS re-render)
💻 Example
Streaming with Suspense Boundaries — A dashboard that streams each section independently for maximum perceived performance.
🤔 Common Confusions
❓ What is the difference between loading.tsx and Suspense?
loading.tsx is a file convention that automatically wraps the entire page in a Suspense boundary. It shows while the whole page loads. Manual Suspense boundaries give you granular control — you can stream individual sections while the rest of the page is already visible. Use loading.tsx for simple cases, manual Suspense for fine-grained streaming.
❓ Can I use Suspense in Client Components?
Yes — Suspense works in Client Components for lazy-loaded components (React.lazy / next/dynamic). But streaming (sending HTML progressively) only works with Server Components. Client Component Suspense shows the fallback while the lazy chunk loads, not while data fetches.
❓ Does streaming affect SEO?
No — search engine crawlers wait for the full page to load before indexing. Streamed content is fully indexed. Streaming is a browser performance optimisation, not an SEO concern.
🚨 Common Production Issues
Suspense boundary too high in the tree — wrapping the entire page in one Suspense boundary gives no streaming benefit (same as no Suspense). Place boundaries around individual slow sections.
Missing Suspense around slow components — a slow Server Component without a Suspense boundary blocks the entire page. Always wrap slow data fetches in Suspense.
Skeleton shape mismatch — skeletons that look nothing like the real content cause jarring layout shifts when content loads. Match skeleton dimensions to real content dimensions.
✅ Best Practices
Place Suspense boundaries around each independently-loading section
Match skeleton shapes to real content to minimise layout shift on load
Move data fetching into the component that needs it — enables independent streaming
Use loading.tsx for simple cases, manual Suspense for fine-grained control
Measure streaming impact with Chrome DevTools waterfall view
🏛️ Architect's Note
Streaming changes the mental model from "wait for all data, then render" to "render what you have, stream the rest". This aligns with how users experience web apps — they want to see SOMETHING immediately, not a blank page for 2 seconds. Design your component tree with streaming in mind: identify slow data fetches and isolate them behind Suspense boundaries.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
↗ Where this topic fits
Next.js Technology Guide
Return to the Next.js learning hub.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Sources
Sources / References
Use these Next.js references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide Next.js learning path
Browse the full Next.js topic collection and learning order on SplashRide.
Next.js Interview Prep
Practice Next.js interview questions and scenario-based answers.
Frontend Engineer Career Path
A beginner-friendly journey through web foundations, React, production frontend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Server Components
Master React Server Components in Next.js — the paradigm that lets components run exclusively on the server, fetch data directly, and ship zero JavaScript to the browser.
Next.js App Router Explained: Server Components, Layouts, and Routing
Learn the Next.js App Router with Server Components, nested layouts, streaming, Route Handlers, data fetching, and Pages Router migration guidance.