Repository navigation
Undici WG meeting: let's fix our governance so we can resolve our disagreements #5989
Description
@nodejs/undici
Over the last couple of years, several PRs have stalled on the same recurring disagreement. It isn't about code quality; it's about what undici's web-platform APIs (fetch, Request, Response, WebSocket) are meant to be. Each of these threads has a reasonable argument on both sides. What's been missing is a way to reach a decision.
Our GOVERNANCE.md says that when collaborators can't reach consensus, the WG is the final arbiter, and the WG decides only in meetings. We haven't been holding those meetings, so these disagreements have nowhere to go. A single objection can hold a PR indefinitely, whatever its merits.
I'm calling a WG meeting with one goal: fix our governance so the WG can decide asynchronously, by vote. The meeting won't try to settle the disagreements itself. Once we have a working process, each item can be put to the WG and decided on its own merits. If we can't agree on such a process, the alternative is to disband the WG and fall back to Node.js TSC decision-making. For context, the addendum lists the open questions that are waiting on this.
Agenda: adopt asynchronous, quorum-based decisions (#5943)
Under the current GOVERNANCE.md, changes to governance are agenda items for a WG meeting. That's why this has to be a meeting rather than another GitHub thread. #5943 proposes:
- Asynchronous decisions: decisions are made on GitHub, and meetings become optional.
- Escalation: mention
@nodejs/undicion the issue or PR. This replaces theWG-agendalabel and the meeting agenda. - Quorum: more than half of WG members have taken part, by approving, objecting, voting or explicitly abstaining.
- Default acceptance: after at least 72 hours, a proposal passes if quorum is reached, at least two WG members approve and none objects. Governance changes stay open for at least 7 days.
- Consensus check: any WG member can ask "Does anyone object?". If nobody objects within 72 hours, consensus is reached.
- Voting when consensus fails:
- Any WG member can call a vote, and another member must second it.
- Votes run in a GitHub issue or with a tool the WG agrees on, such as
git node voteor OpaVote. Both support secret ballots. - A vote stays open for at least 7 days, or until every member has voted.
- Quorum is required. A simple majority of votes cast wins, not counting abstentions. Without quorum or a majority, the current state is kept.
- Membership and nominations: both follow the same asynchronous process.
- Private matters: anything that can't be discussed in public, such as security, goes to the OpenJS Slack or email.
- Code of Conduct: handled by the Node.js moderation policy rather than the WG.
Decision needed: adopt #5943, as is or amended. Please review it before the meeting and leave comments on the PR, so that we spend the meeting on whatever is still unresolved.
If we can't fix our governance
The status quo isn't an option. A WG that can't meet and can't decide leaves the project without a working arbiter. If we can't agree on a process that lets the WG decide, the alternative is to disband the undici WG and fall back to the Node.js TSC for decision making, as undici is a Node.js project. I'd much rather we keep these decisions within the people who maintain undici. That depends on us fixing our process.
Logistics
- Format: Zoom, recorded and published per GOVERNANCE.md. I'll volunteer to moderate unless someone else would prefer to.
- Scheduling: please add your availability here: https://rallly.co/invite/dywBVDaRpfyq. I'd like to hold the meeting within the next two weeks.
- Length: one agenda item, so 30 minutes should be enough.
None of this is about who's right on any of the questions below. Everyone in these threads cares about undici and has put a lot into it. We need a process that lets us decide and move on, instead of leaving PRs blocked indefinitely.
Addendum: open questions to resolve by vote
These are not on the meeting agenda. They're listed here so it's clear why the governance change matters. Once #5943 lands, each one will be brought to the WG with @nodejs/undici and decided asynchronously. If I've misstated a position or missed an open question, please comment here.
The two positions
I've tried to state both fairly.
Spec compliance. Undici's web classes are implementations of WHATWG specs.
- Anything the spec doesn't define is drift: Node-specific hooks, extra prototype members, server-side tuning, or behaviour that departs from the spec algorithms.
- Drift makes the code harder to maintain as living standards evolve, and it hurts interop with other runtimes.
- Node-specific needs belong in undici's own APIs (
request, dispatchers, interceptors), not in the web classes. - Code that follows the spec step by step is easier to keep correct than optimized code.
Node.js compatibility and the security model. Undici's web classes are the Node.js implementations of web APIs, and undici is part of the Node.js org.
- They should take part in Node.js platform mechanisms the way core defines them: the refable protocol and
diagnostics_channel/TracingChannel. - They should follow the Node.js threat model and security policy.
- Where the spec is silent, behaviour is implementation-defined. Adding to it is allowed as long as no normative requirement, Web Platform Test or real application breaks.
- Performance for Node.js users is a legitimate goal when the change isn't observable.
Both positions are right about a lot. The spec-compliance view keeps our implementations correct and maintainable. The Node-compatibility view keeps them useful and consistent with the rest of the platform. The question is where the line goes.
A. Guiding principle for undici's web APIs
A short written principle that we add to the repo and point to in reviews. My proposal, as a starting point:
Undici's web classes are Node.js implementations of web specs. They:
- follow the spec algorithms and pass the Web Platform Tests;
- take part in Node.js platform protocols (such as the refable protocol and
diagnostics_channel) the way Node.js core defines them;- follow the Node.js threat model and security policy;
- may optimize internals when the change isn't observable to spec tests.
Objections to a Node.js platform protocol itself belong in nodejs/node, not in undici.
If we agree on a principle like this, most of the questions below resolve themselves.
B. Refable protocol on WebSocket (#5793, #5795, #5798)
#5578 added Node.js's refable-protocol symbols (kRef/kUnref) to WebSocket to fix #5570. The change shipped in undici and Node.js releases.
- Concern: the symbols are observable on
WebSocket.prototype. WebIDL and HTML discourage extending interfaces, and WPTs check prototype shape for other interfaces. - Counterpoint:
- Node.js core defines the refable protocol in terms of these symbols;
process.ref()/process.unref()look them up on the object. This is how WHATWG objects in Node.js are meant to take part in event-loop ref counting. - No normative requirement, WPT or known application breaks.
- WebIDL lets a class implement more than one interface.
- Node.js core defines the refable protocol in terms of these symbols;
- Proposed compromise: standalone
ref(websocket)/unref(websocket)helpers, similar toping(websocket). My concern is that this would makeprocess.ref(websocket)stop working and give undici an API no other Node.js object has. - Open PRs:
- revert #5578 #5793 reverts the symbols. It has two change requests.
- fix(websocket): make WebSocket kRef/kUnref non-enumerable #5795 makes the symbols non-enumerable, and fix(websocket): add brand-checks to WebSocket kRef/kUnref #5798 adds brand checks. Each is blocked by one change request. They address the parts of the concern that can be fixed while keeping the protocol.
Question for the vote: keep the symbols, land #5795 and #5798 and close #5793; or remove the symbols and accept the interop cost with process.ref().
C. TracingChannel instrumentation in fetch (#2701)
This PR adds diagnostics_channel tracing to fetch so that APMs and OpenTelemetry can trace fetch calls.
- Concern:
- It adds Node-specific steps to the fetch algorithm ("Node-ifying fetch"), and spec deviations tend to cause problems later.
- It originally relied on
dc-polyfillfor Node 18. - Tracing could go through undici's other APIs instead.
- Counterpoint:
TracingChannelis a Node.js core feature, and observability is needed by almost every production Node.js application.- The change to the algorithm is small and costs nothing when there are no subscribers.
dc-polyfillno longer matters because Node 18 is out of support.
- Status: four approvals. We proposed a call in 2024, but it never happened, and the PR has been stalled ever since.
Question for the vote: land #2701, whether as is or rebased onto an interceptor-based design that leaves the fetch algorithm untouched; or decide that fetch won't emit tracing events.
D. Security model for the WebSocket client (#5447)
The WebSocket client gained a frame-size cap to address a decompression-bomb DoS.
- Concern: a frame cap blocks legitimate large frames and prevents zip bombs only as a side effect. Letting users disable permessage-deflate addresses the cause.
- Counterpoint: removing or replacing the cap changes the security model in a way that is incompatible with the Node.js threat model.
- Process question: how do maintainers of a component take part in security fixes to that component?
Question for the vote: whether a permessage-deflate opt-out is added alongside the frame cap or instead of it, and how component maintainers are brought into future security fixes. Any part of this that can't be discussed publicly can go to the private channel.
E. Server-side use of Request/Response (#5415)
This PR initializes Request/Response internals lazily so they're cheaper to construct, which matters most on the server side.
- Concern:
- These are client-side browser APIs and don't fit an HTTP server (WebSocket, extended CONNECT, HTTP/3).
- Server-side tuning makes
fetchharder to maintain. - Frameworks that need speed bypass these classes anyway.
- Counterpoint:
- The ecosystem is converging on
Request/Responseas the server-side API (Workers, WinterTC). - Full client-side fetch compliance is already not a goal, since Node.js doesn't implement CORS.
- The alternative is yet another runtime-specific API. See the HTTP server API draft.
- The ecosystem is converging on
Question for the vote: is optimizing Request/Response for server-side use in Node.js in scope for undici?
F. Performance changes that aren't observable (#4349, #5010)
- fetch: make readAllBytes sync #4349 makes
readAllBytessynchronous, which saves one promise per body read. It has two approvals and one change request. - feat(streams): limit usage in body mixin #2164 #5010 adds a fast path to the body mixin. It has one change request. That review also found a real correctness gap: the fast path skips
Uint8Arrayvalidation. The gap has to be fixed regardless of the outcome here. - Concern: small gains don't justify moving away from code that follows the spec, and type-specialized fast paths push users toward engine-specific patterns.
- Counterpoint:
fetchis on Node.js's hot path, and allocation savings that aren't observable are good for every user.
Question for the vote: are optimizations that aren't observable and pass the WPTs acceptable by default, with correctness issues handled in normal review?
Part of this messages where drafted by AI under my guidance.
Activity
ronag commentedon Oct 9, 2026
IMHO we should implement the web api's the same way as Node is implementing other ones, i.e. we should adopt the NodeJS policy. undici is part of the node org and should therefore follow its conventions.
KhafraDev commentedon Oct 9, 2026
undici has always been better than node's web apis. I don't see why we'd willingly drop undici to node's level.
edit: excluding WebSocket and EventSource, which have already been dropped to node's level and are worse than their npm counterparts
jasnell commentedon Oct 9, 2026
Undici is a Node.js project. If the Undici WG does not have functional working group governance then responsibility falls to the @nodejs/tsc to make a decision around whether to maintain or revoke the Undici WG charter.
KhafraDev commentedon Oct 9, 2026
I don't mind either way 🤷. I'm already burned out from working on undici after a 2 month break (what got implemented during that break largely contributed to me burning out again). I don't have the motivation to join meetings so others can decide what does or doesn't get implemented.