AniUI Academy

Streaming SSR and Suspense

Why waiting for the slowest data on a page before sending any HTML is wasteful, and how streaming SSR with Suspense sends the fast parts first.

11 min read

Traditional SSR has an uncomfortable property: the response is only as fast as its slowest dependency. If a page needs three data sources and two resolve in 20ms while the third takes 800ms, the entire HTML document waits 800ms, even though most of the page was ready almost immediately. Streaming SSR exists to break that all-or-nothing dependency.

Sending the page in pieces, not one block

Streaming SSR keeps the HTTP connection open and sends HTML in chunks as it becomes ready, instead of buffering the entire document before sending anything. React's <Suspense> boundary is the mechanism that marks where this can happen: wrap a slow part of the tree in <Suspense fallback={...}>, and the server is now allowed to send everything outside that boundary immediately, substitute a fallback in its place, and stream the real content in later.

  1. Step 1

    Server starts rendering

    Fast, already-resolved parts of the tree render normally.

  2. Step 2

    A Suspense boundary is hit

    Its subtree isn't ready yet, so the fallback renders in its place instead of blocking.

  3. Step 3

    The first HTML chunk ships

    The browser receives real content immediately — header, layout, everything outside the boundary — and starts painting.

  4. Step 4

    The slow data resolves

    The server renders the real content for that boundary and streams it as an additional chunk, along with a small inline script.

  5. Step 5

    The browser swaps it in

    That script replaces the fallback with the real content, in place, without a full page reload or a client-side re-fetch.

One HTTP response, multiple HTML chunks — the slow part arrives later without holding up the fast parts.

Why this beats the alternatives

Compare the three options for a page with one slow section: blocking SSR delays the entire response for everyone, even users who only cared about the fast parts. CSR for the slow section ships a client-side spinner and fetches after the JS bundle loads and hydrates — strictly slower than starting that fetch on the server the moment the request comes in, and it loses SEO for that content. Streaming SSR starts the slow fetch on the server immediately (often before the client has even received a single byte), ships everything else without waiting, and streams the result in the moment it's ready — the best of both, at the cost of needing a runtime that supports HTTP streaming and a framework that wires Suspense into it.

What streaming does not fix

It's important to be precise about what problem this solves. Streaming SSR doesn't make a slow data source faster — the recommendations API that takes 800ms still takes 800ms. What changes is that 800ms no longer blocks everything else. It also doesn't remove the cost of hydration (covered next): the streamed-in content still needs to become interactive, and that's a separate, additional cost layered on top. And it introduces real infrastructure requirements — your hosting needs to support streaming responses, which rules out some simpler static-hosting-plus-function setups unless they're specifically built for it.

When to reach for it

Streaming SSR earns its complexity on pages with a clear split between fast-and-critical content and slow-and-less-critical content: a product page where the price and buy button are fast but "customers also bought" is slow; a feed where the first few posts are prefetched but personalization runs a heavier query. It's not worth the added infrastructure complexity for a page where everything resolves in roughly the same, already-fast time — there's nothing to unblock.

What to remember

  • Traditional SSR sends one complete document only once every data dependency has resolved — the slowest one sets the pace for the whole page.
  • Suspense boundaries let the server ship fast content immediately and stream in slow content afterward, as additional HTML chunks over the same connection.
  • Streaming doesn't make a slow fetch faster — it stops that slowness from blocking unrelated, faster content.
  • It requires streaming-capable infrastructure and still leaves hydration cost on the table; it solves "time to first content," not "time to interactive."

Check yourself

3 questions · pass 3/3 to unlock Hydration and Why It's Expensive

up to 50
  1. 1.In traditional (non-streaming) SSR, why does one slow data source on a page delay the entire response?

  2. 2.What does wrapping a slow component in <Suspense> change about a streaming SSR response?

  3. 3.A page has a fast header/nav and a slow, personalized recommendations section below the fold. Why is streaming SSR a good fit here specifically?

3 left to answer