0Pricing
React Academy · Lesson

Streaming SSR from the Edge

Stream React's HTML output using ReadableStream so the browser can paint meaningful content immediately.

Streaming SSR from the Edge is a free React Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The Streaming Advantage

When a server streams HTML, the browser receives and renders content in chunks rather than waiting for the complete document. This means users see and interact with the visible parts of the page — the header, navigation, hero section — while slower data-dependent sections are still loading.

renderToReadableStream with bootstrapScripts

Passing bootstrapScripts to renderToReadableStream tells React where the client-side JS bundle lives. React injects a script tag at the end of the stream so the browser loads the bundle and calls hydrateRoot, making the page interactive as each section finishes streaming.

Suspense Boundaries in the Tree

React's streaming relies on Suspense boundaries to split the component tree into independently streamable sections. Components inside a Suspense boundary that are waiting for data (via a thrown Promise) stream as placeholders first, then resolve and stream their real content later.

onShellReady: When to Start Streaming

The onShellReady callback fires when the non-suspended HTML shell — everything outside of Suspense boundaries — is ready to stream. This is the correct moment to set the HTTP status code and response headers, then call pipe(res) or begin reading from the ReadableStream.

Why Status Codes Must Be Set First

HTTP status codes and headers must be sent before the response body begins. Because streaming starts with onShellReady, any error handling logic (setting status 500, redirecting) must happen before the shell starts flowing — once streaming begins, the status code is locked.

Error Handling: onShellError

onShellError fires when a fatal error occurs before the shell is ready — for example, an error in a top-level component outside any Suspense boundary. In this case, the shell never streams, and you should respond with a static error page or redirect to an error route.

Error Handling: onError

onError fires for recoverable errors within Suspense boundaries. React can still stream the rest of the page; the errored boundary renders its error fallback UI. Use onError for logging: capture the error to your observability platform without aborting the stream.

Progressive Enhancement and Timeouts

If a Suspense boundary's data takes too long, stream the shell anyway and let the boundary hydrate on the client. Implement a timeout: after 5 seconds, call abort() on the stream if the boundary hasn't resolved, and the client will fetch the data itself via useEffect.

Cloudflare Workers Streaming Mechanics

The Workers runtime passes the ReadableStream directly as the Response body. Cloudflare's infrastructure forwards each chunk to the user's browser as React produces it, without buffering the entire document. This means the first bytes of HTML leave the edge PoP within milliseconds of the request arriving.

Abort: Controlling Long Streams

renderToReadableStream returns an abort controller function. If the request is cancelled (user navigates away), calling abort() stops React from continuing to render and process data. This prevents wasted computation on orphaned requests and keeps Worker CPU usage bounded.

End-to-End Latency Profile

With edge streaming, the full latency chain looks like: 5ms (request to nearest PoP) + 2ms (Worker cold start) + 8ms (shell render) = 15ms to first byte. The user's browser renders the LCP element from the shell while the rest of the page continues streaming in the background.

onShellReady Timing

When exactly does the onShellReady callback fire during streaming SSR?

Lesson Recap

Streaming SSR from the edge delivers HTML in chunks, improving FCP and LCP by sending the shell immediately. Suspense boundaries divide the tree into independently streamable sections. onShellReady is the signal to start piping — set status codes before calling it. onShellError handles fatal failures, onError handles recoverable ones, and abort() prevents wasted work on cancelled requests.

Frequently asked questions

Is the “Streaming SSR from the Edge” lesson free?

Yes — the full text of “Streaming SSR from the Edge” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.

What will I learn in “Streaming SSR from the Edge”?

Stream React's HTML output using ReadableStream so the browser can paint meaningful content immediately. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start React Academy?

No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Streaming SSR from the Edge” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this React Academy lesson?

Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. What Is Edge Rendering and Why It Matters
  2. React on Cloudflare Workers with Hono
  3. Streaming SSR from the Edge
  4. Edge Caching Strategies for React Apps
← Back to React Academy