[Flight] Server References for arbitrary object types #37636

Open
acdlite opened 1:11pm on September 15, 2026 wants to merge 1 commit into facebook/react main from
codex/server-object-references

Pull Request Overview

  • Opened on September 15, 2026
  • Status Open
  • Commit count 1 with first commit August 10, 2026

Total Delta

0 Total Diff Delta

Open Days

Open 4 weekdays

Test Delta

0 Diff Delta in Test Files
Breakdown by Phase

How long has this pull request spent in each phase of its lifecycle?

Fraction of total time Business days Phase
 
26.6 days Authoring 1 commit before pull request opened for review
 
0.0 days Awaiting first review
 
3.0 days Revising work with 0 commits in response to 1 review that left 2 comments

Total time for pull request still awaiting merge (longer than repo's target): 29.6 business days

Author avatar

[Flight] Server References for arbitrary object types

Added behind a new experimental flag, enableFlightObjectReferences.

Extends Server References so that a reference can point to an object, not just a function. An object is registered with a new API, registerServerObjectReference, which tags it with its module id the same way registerServerReference tags a Server Function.

The client receives an opaque handle: reading a property or calling it throws, similar to how Temporary References work inside Server Functions. The only thing the client can do with the handle is pass it back to the server via a Server Function, where it resolves through the server manifest.

The motivating use case is letting a framework pass request-scoped values by reference, so it can omit them from the request body. For example, a framework could model searchParams as a module export whose value resolves from the current request. This avoids encoding the search params twice (they already appear in the request URL) but it also makes the responses more cacheable: if the search params don't appear elsewhere in the body, then a response cache can omit them from its cache key.

This initial PR only exposes the new API in the Turbopack bindings. We will port it to the other bundler configs if the experiment advances.

Comments Threads Pending Resolution

unstubbable reviewed on September 16, 2026
unstubbable left a comment

One concern with reply decoding: once an object reference resolves, `getOutlinedModel()` allows a deduplication path to traverse its own properties if it's a plain object or array. It doesn't distinguish objects decoded from the client payload from objects resolved through the server manifest.

That seems to let a crafted reply do more than pass the opaque reference back. For example, it can select a string property from a registered object and supply that value to a Server Action. If the action echoes that argument, the property becomes readable on the client without the action explicitly accessing the referenced object.

The path-resolution behavior already exists, but this feature makes server-owned objects supported manifest entries. Could we prevent reply property paths from traversing resolved server objects? This would also need to cover object IDs submitted through the existing `$h` path, not just `$H`.

Separately, one admittedly niche edge case: if an async iterable yields a registered typed array or `ArrayBuffer`, `emitChunk()` serializes its bytes before it reaches the object-reference check. The same value passed as an ordinary property correctly becomes an opaque reference.

Probably uncommon, but this loses reference identity on the client within the same response and means a round trip sends the bytes back instead of resolving the module export. Could we check for registered object references in `emitChunk()`, before the binary fast paths?

Resolved Comment Threads

No resolved comments have been left on this PR.