Fizz Streaming Instruction Set
Fizz’s instruction set is the small browser-side runtime that turns streamed server output into DOM updates. It replaces Suspense fallbacks, inserts completed segments, handles errored boundaries, waits for boundary stylesheets, and records form submissions for later replay.
It exists because HTML and its completed Suspense content can arrive separately and out of order. The runtime preserves placeholder positions, queues boundary reveals, and lets hydration or client rendering win when the original tree is no longer available.
Sources: packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:32-101, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:408-461
Core concepts
Suspense boundary
A Suspense boundary is represented by marker nodes and a fallback region; its marker data identifies whether it is pending, queued, or requires client rendering.
Sources: packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:12, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:13, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:14
Segment
A segment is detached completed content stored in a container until completeSegment or completeBoundary moves it into the live DOM.
Instruction node
An instruction node is a streamed element carrying dataset fields that tell the runtime which operation to perform, such as client rendering, stylesheet-aware completion, boundary completion, or segment completion.
Sources: packages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js:71-99
Inline and external runtimes
The inline runtime is emitted as generated JavaScript strings, while the external runtime observes streamed instruction nodes and dispatches them to shared functions.
Sources: scripts/rollup/generate-inline-fizz-runtime.js:48-101, packages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js:47-69, packages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js:71-99
How streamed chunks change the DOM
The three completion operations differ in whether they queue a reveal, replace a placeholder immediately, or mark a fallback for client rendering.
| Operation | Input nodes | DOM effect | Ordering behavior |
|---|---|---|---|
completeBoundary | Suspense boundary ID and content ID | Queues the completed content and later replaces the fallback | Batches multiple completions |
completeSegment | Container ID and placeholder ID | Moves every child before the placeholder and removes both wrappers | Applies immediately |
clientRenderBoundary | Boundary ID and error metadata | Marks the fallback for client rendering and invokes its retry hook | Stops if the boundary disappeared |
completeBoundaryWithStyles | Boundary ID, content ID, and stylesheet descriptors | Registers or hoists styles, waits for dependencies, then completes the boundary | Delays reveal until relevant styles settle |
completeBoundary first locates the streamed content. If that content is gone, it returns; if the fallback marker is gone, it removes the content because the boundary will never be revealed. Otherwise it marks the boundary as queued and pushes the boundary and content nodes into the reveal batch.
The queued batch is flushed on the next animation frame before the first paint, or through a throttled timer afterward. The throttle uses TARGET_VANITY_METRIC and FALLBACK_THROTTLE_MS to decide when to flush.
When the reveal batch runs, the content container is detached, the fallback and its nested marker range are removed, and the content children are inserted before the boundary’s end marker. The boundary marker is then changed back to the normal Suspense start marker and its retry hook is scheduled.
This is why out-of-order completion works: a completed inner boundary can be detached into its designated place before an outer fallback is removed, while a missing or already-hydrated boundary is safely skipped.
completeSegment follows a simpler path. It removes the segment container, repeatedly moves its first child before the placeholder, and finally removes the placeholder itself.
clientRenderBoundary instead changes the fallback marker to SUSPENSE_FALLBACK_START_DATA, stores any supplied error metadata in the marker dataset, and calls _reactRetry when the parent has already hydrated.
This sequence shows the external-runtime dispatch path and the queued reveal path for a streamed completion.
Evidence
- instruction-nodepackages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js:71
- mutation-observerpackages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js:48
- boundary-runtimepackages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:408
- reveal-batchpackages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:32
Sources: packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:408-461, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:589-603, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:378-406, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:463-587, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:408-437, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:439-458, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:16, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:24, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:32-101, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:417-429, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:14
How stylesheet-aware completion waits
completeBoundaryWithStyles first scans existing precedence-ordered link and style nodes. It records existing resources, collects style tags whose media is not all, and uses the precedence map to preserve stylesheet ordering.
For each stylesheet descriptor, it reuses an existing resource or creates a link element with rel="stylesheet" and the declared precedence. New resources receive a loading promise resolved by onload and rejected by onerror; matching media conditions add those promises to the dependency list.
After stylesheet mode, the function hoists pending style tags and inserts resources according to their precedence. The inline form then marks the boundary queued and calls the normal completion function only after Promise.all resolves; a stylesheet failure calls clientRenderBoundary with "CSS failed to load".
The hand-off is therefore “register and order styles first, await active dependencies second, reveal content third.” This prevents the boundary from becoming visible before its precedence stylesheets have finished loading.
Evidence
- style-descriptorspackages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:463
- style-runtimepackages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:463
- style-dependenciespackages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:488
- boundary-completionpackages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings.js:12
Sources: packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:468-485, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:497-541, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:463-587
How the runtime is built and selected
The build script maps seven entry files to generated exports, including clientRenderBoundary, completeBoundary, completeBoundaryWithStyles, completeSegment, and formReplaying.
main constructs a ClosureCompiler for each entry, includes the entry and shared instruction-set source, compiles with ADVANCED optimization from ECMAScript 2020 to ECMAScript 5 strict mode, and disables polyfill rewriting.
The compiled output is trimmed, flattened into a JavaScript string, formatted with prettier, and written to inlineCodeStringsFilename. The generated file therefore contains source-derived inline instruction strings rather than the unminified shared functions.
Fizz uses the external-runtime path when externalRuntimeConfig is supplied and the enableFizzExternalRuntime feature flag is set; in that mode the server sends instruction data attributes instead of inline scripts.
The external runtime scans existing template nodes and observes added nodes with MutationObserver. Its dispatcher maps dataset markers to window['$RX'], window['$RR'], window['$RC'], and window['$RS'], then removes the instruction node.
Sources: scripts/rollup/generate-inline-fizz-runtime.js:15-44, scripts/rollup/generate-inline-fizz-runtime.js:48-101, scripts/rollup/generate-inline-fizz-runtime.js:12-13, scripts/rollup/generate-inline-fizz-runtime.js:46, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:382-395, packages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js:40-45, packages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js:47-69, packages/react-dom-bindings/src/server/ReactDOMServerExternalRuntime.js:71-99
How it connects
Fizz server rendering emits pending boundaries and completed segments that this instruction set later places into the browser DOM.
The DOM renderer’s configuration decides whether a boundary needs stylesheet insertion and ensures the client-render and completion instructions are sent before the stylesheet-aware instruction that depends on them.
Form replaying sits beside boundary completion: it listens for submissions whose action equals EXPECTED_FORM_ACTION_URL, prevents native navigation, snapshots FormData, and queues the form, submitter, and data on the root for hydration to replay.
For the broader server-rendering pipeline, see Server Rendering (Fizz) and Fizz Server Internals For stylesheet ownership, see Resource Hoisting & Preloading (Float)
Sources: packages/react-server/src/ReactFizzServer.js:5910-5926, packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js:5026-5042, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:608-610, packages/react-dom-bindings/src/server/fizz-instruction-set/ReactDOMFizzInstructionSetShared.js:612-665
Key takeaways
completeBoundaryqueues completed content so fallback removal and insertion can be batched.completeSegmentimmediately replaces a placeholder with detached segment children.clientRenderBoundarymarks an errored fallback and triggers a retry when possible.completeBoundaryWithStyleswaits for matching stylesheet promises before revealing content.- Build-time Closure compilation produces inline strings; configured external runtime mode uses streamed data attributes instead.