Skip to content

http2: tune control flow defaults - #61036

Open
ronag wants to merge 1 commit into
nodejs:mainfrom
ronag:http2-tune
Open

http2: tune control flow defaults#61036
ronag wants to merge 1 commit into
nodejs:mainfrom
ronag:http2-tune

Conversation

@ronag

Copy link
Copy Markdown
Member

The current defaults are unnecessarily conservative which makes http2 control flow over high latency connections (such as public internet) unbearably slow.

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/http2
  • @nodejs/net

@nodejs-github-botnodejs-github-bot added http2 Issues or PRs related to the http2 subsystem. needs-ci PRs that need a full CI run. labels Dec 12, 2025
@ronag

Copy link
Copy Markdown
MemberAuthor

I'm unsure about the relationship between request window size (initialWindowSize) and connection window size (connectionWindowSize). But I assume it's ok to have a 1:2 relationship. 🤷

@ronag

Copy link
Copy Markdown
MemberAuthor

This affects UPLOAD speed, i.e. data to server.

Comment threadlib/internal/http2/core.js Outdated
this.emit('session', session);
}

function initializeOptions(options) {
assertIsObject(options, 'options');
options = { ...options };
options = { ...getDefaultSettings(), ...options };

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

We should actually apply the default settings and not just assume that they are the same as nghttp2 will do.

@ronag
ronagforce-pushed the http2-tune branch 3 times, most recently from eae93cc to f6fa8faCompareDecember 12, 2025 16:47
@codecov

codecovBot commented Dec 12, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.49%. Comparing base (d9cf867) to head (bb77aed).
⚠️ Report is 1118 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #61036 +/- ##
==========================================
- Coverage 88.58% 88.49% -0.10% 
==========================================
Files 704 703 -1 Lines 207815 208557 +742 Branches 40036 40198 +162 ==========================================
+ Hits 184102 184571 +469 - Misses 15758 16019 +261 - Partials 7955 7967 +12 
Files with missing linesCoverage Δ
lib/internal/http2/core.js93.85% <100.00%> (-1.36%)⬇️
lib/internal/http2/util.js92.74% <100.00%> (+0.05%)⬆️

... and 152 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mcollinamcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

I think this might require a doc change too

@mcollinamcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@ronagronag added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 14, 2025
@pimterry

Copy link
Copy Markdown
Member

I'm unsure about the relationship between request window size (initialWindowSize) and connection window size (connectionWindowSize). But I assume it's ok to have a 1:2 relationship. 🤷

My understanding is they are overlapping limits: if sending any byte would go over the receiver's window for the connection or the window for the specific stream, then you have to wait. That means a 1:2 ratio only lets 2 streams fully using their windows at any time - beyond that, streams are fighting for bandwidth. Similarly, if you're handling lots of streams on a single connection, it means 2 busy streams start to starve all the others.

Concrete numbers: with this specific setting, with 256KB/512KB stream/connection windows on a 100ms latency connection, each stream can use ~2.5MB/s (i.e. 20mbps) and the entire connection across all streams can use 5MB/s.

Imo, 1:2 seems a touch conservative still, I'd be happy to go a few multiples further, but ofc if we want to really get into this we'd need to measure a bunch of scenarios in a lot more detail, and trying to do some kind of dynamic optimization instead as mentioned in Slack would make more sense anyway.

Still a very significant improvement though regardless, so I'm all aboard as-is, very happy to ship this 👍. We can bikeshed & tweak further later as feedback comes in.

@aduh95aduh95 added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Dec 19, 2025
@github-actionsgithub-actionsBot removed the request-ci Add this label to start a Jenkins CI on a PR. label Dec 19, 2025
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@aduh95aduh95 removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Dec 26, 2025
@ronagronag added request-ci Add this label to start a Jenkins CI on a PR. author ready PRs that have at least one approval, no pending requests for changes, and a CI started. labels Apr 8, 2026
@github-actionsgithub-actionsBot added request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. and removed request-ci Add this label to start a Jenkins CI on a PR. labels Apr 8, 2026
@github-actions

Copy link
Copy Markdown
Contributor
Failed to start CI
- Validating Jenkins credentials
✔ Jenkins credentials valid
- Querying data for job/node-test-pull-request/70522/
[SyntaxError: Unexpected token '<', ..." https://github.com/nodejs/node/actions/runs/24120621083

The current defaults are unnecessarily conservative which makes http2 control flow over
high latency connections (such as public internet) unbearably slow.

@RafaelGSSRafaelGSS left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't it be flagged as semver-major?

@mcollinamcollina added the request-ci Add this label to start a Jenkins CI on a PR. label Apr 8, 2026
Qard
Qard approved these changes Apr 8, 2026
@github-actionsgithub-actionsBot removed the request-ci Add this label to start a Jenkins CI on a PR. label Apr 8, 2026
@github-actions

Copy link
Copy Markdown
Contributor
Failed to start CI
- Validating Jenkins credentials
✔ Jenkins credentials valid
- Querying data for job/node-test-pull-request/70522/
[SyntaxError: Unexpected token '<', ..." https://github.com/nodejs/node/actions/runs/24164427109

@mcollina

Copy link
Copy Markdown
Member

@ronag can you fix the commit message?

@avivkeller

Copy link
Copy Markdown
Member

Bump @ronag

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author readyPRs that have at least one approval, no pending requests for changes, and a CI started.http2Issues or PRs related to the http2 subsystem.needs-ciPRs that need a full CI run.request-ci-failedAn error occurred while starting CI via request-ci label, and manual interventon is needed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@ronag@nodejs-github-bot@pimterry@mcollina@avivkeller@Qard@RafaelGSS@aduh95