Module A-1·28 min read

The RSC wire format, React Flight serialisation, how the client reconciler processes RSC payloads, React 19 async params/searchParams as Promises, and the React Compiler's automatic memoisation model.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

A-1 — RSC Internals: The React Flight Protocol and React 19

Who this is for: Architects who want to understand what's actually happening when a Next.js App Router page renders. This module goes below the abstraction — into the React Flight wire format, how the client reconciler processes RSC payloads, why client-side navigation in the App Router preserves Client Component state, and what React 19 changed. This is the layer that makes everything else in the Architect phase make sense.


What React Flight Actually Is

When engineers say "React Server Components," they're describing a rendering model. When they ask what's transmitted over the wire, the answer is React Flight — a serialisation protocol designed specifically for streaming React component trees from server to client.

Flight is not JSON. It's not HTML. It's a line-delimited text format where each line represents one unit of work in the React tree. Understanding its structure is how you understand why RSC works the way it does and why it has the constraints it has.

A minimal Flight payload looks like this:

text

Line by line:

  • 1:I[...]Module reference. I means import. This declares that a Client Component exists at the given file path and chunk. It never contains the component's source code — only a reference.
  • 0:[...]React element tree. The server's rendered output, as a JSON-like structure. "$1" references the module declared on line 1. The server rendered everything it could; where a Client Component appears, it left a placeholder that points to the client bundle.

This is the key insight: the server renders Server Components to their final output. For Client Components, it emits a module reference ($1, $2, etc.) and stops. The client downloads those module references, renders the Client Components in the browser, and stitches the result into the tree React received from the server.


The Payload Type System

React Flight uses single-letter prefixes to identify what each line contains:

PrefixMeaning
IImport — a module reference to a Client Component chunk
MModule — similar to I, alternative format
TText — a large string value, usually inline HTML
SSymbol — a React special value (Suspense, Fragment, etc.)
EError — a thrown error (for error boundary activation)
HHint — a preload/prefetch directive

Suspense boundaries in the payload cause the server to flush a partial payload immediately, with a placeholder for the pending content. When the async data resolves, the server writes another chunk with the filled-in content. The client reconciler knows how to patch the placeholder without re-rendering the static parts of the tree.


How the Client Reconciler Processes a Flight Payload

When you navigate in the App Router, the browser doesn't receive HTML — it receives a Flight payload for the new page's Server Components. React processes it through createFromFetch() (or createFromReadableStream() for streaming responses):

text

Step 6 is what makes App Router navigation feel different from a page reload. When you navigate from /dashboard to /dashboard/settings, React doesn't unmount and remount the dashboard layout Client Components. It reconciles the server-rendered output of the new page against the existing tree, leaving any Client Component state intact.

This is why a Client Component inside a persistent layout doesn't lose its state during navigation — the reconciler sees it's the same component at the same position in the tree and preserves it.

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.