Skip to content

renderHTML: unused tee branches buffer entire RSC payloads in memory #146

Description

@uhyo

Problem

renderHTML in packages/static/src/ssr/entry.tsx unconditionally tees the incoming RSC stream:

const [rscStream1, rscStream2] = rscStream.tee();

rscStream2 is only consumed in dev when no clientRscStream is provided. In two cases it is never read or cancelled:

  • build mode (options.build === true): the payload injection step is skipped entirely;
  • dev non-SSR (clientRscStream provided): the shell stream's second branch is unused.

A tee() branch that is never read causes the stream implementation to queue every chunk for it without bound, so the entire RSC payload is buffered in memory per render (per entry during builds).

Suggested fix

Only tee when the second branch will actually be used, or rscStream2.cancel() in the paths that don't consume it.

Found during a framework audit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions