Skip to content

fix: Cloudflare streaming response backpressure#1186

Open
Cooperrr wants to merge 8 commits into
opennextjs:mainfrom
Cooperrr:cloudflare-streaming-response-backpressure
Open

fix: Cloudflare streaming response backpressure#1186
Cooperrr wants to merge 8 commits into
opennextjs:mainfrom
Cooperrr:cloudflare-streaming-response-backpressure

Conversation

@Cooperrr

@Cooperrr Cooperrr commented Jun 16, 2026

Copy link
Copy Markdown

Prevents excessive memory usage when streaming large responses. Previously, writes did not account for consumer backpressure, so a fast producer could buffer large amounts of data when the consumer was slow. This PR pauses pulling from the producer until the consumer is ready for more data.

Also skips ReadableStream.tee() when chunks do not need to be retained, avoiding an unused duplicate response body during direct streaming.

@changeset-bot

changeset-bot Bot commented Jun 16, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 961a03b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@opennextjs/aws Patch
app-pages-router Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@khuezy

khuezy commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Hi thanks for the PR! LGTM but I'll defer to the Cloudflare folks.

@pkg-pr-new

pkg-pr-new Bot commented Jun 16, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@opennextjs/aws@1186

commit: 961a03b

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves streaming behavior in the Cloudflare Node wrapper and the core request handler by respecting downstream backpressure to prevent unbounded buffering/memory growth, and by avoiding unnecessary ReadableStream.tee() when the streamed chunks don’t need to be retained.

Changes:

  • Implement backpressure-aware bridging from Node Writable to Web ReadableStream in the Cloudflare Node wrapper.
  • Update openNextHandler streaming path to use pipeline(Readable.fromWeb(...), response) and skip tee() when StreamCreator.retainChunks === false.
  • Add unit tests covering bounded streaming, cancellation/destruction behavior, and tee() skipping/retention semantics.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/open-next/src/overrides/wrappers/cloudflare-node.ts Adds backpressure-aware streaming bridge and producer teardown handling.
packages/open-next/src/core/requestHandler.ts Uses pipeline for proper backpressure and conditionally skips ReadableStream.tee() based on retainChunks.
packages/open-next/src/types/open-next.ts Documents retainChunks: false behavior and tee() avoidance.
packages/tests-unit/tests/overrides/wrappers/cloudflare-node.test.ts Adds streaming/backpressure + cancellation/destruction unit coverage for the Cloudflare wrapper.
packages/tests-unit/tests/core/requestHandler.test.ts Adds unit coverage for tee() skipping/retention and bounded streaming in openNextHandler.
.changeset/cloudflare-stream-backpressure.md Changeset entry describing the patch behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/tests-unit/tests/overrides/wrappers/cloudflare-node.test.ts Outdated
Comment thread packages/tests-unit/tests/core/requestHandler.test.ts Outdated

@conico974 conico974 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you fix the tests as well please.

for await (const chunk of bodyToConsume) {
response.write(chunk);
let bodyToConsume = routingResult.body;
if (options.streamCreator.retainChunks !== false) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change, this PR cannot just be a patch.
It will also likely break some converters that relies on the body being readable
We could gate that under an env variable that we'll remove on a future major

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to review.

I've reverted back to keeping a copy of the body to avoid breaking changes (would be nice to remove down the line as you mentioned in a future major) but not essential for this PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add more comment on your change please, this is quite hard to review and follow what's going on

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to better explain what's going on with 961a03b

@Cooperrr Cooperrr requested a review from conico974 June 16, 2026 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants