Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Undici WG meeting: let's fix our governance so we can resolve our disagreements

Open
#5,989 5 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
3/100
Issue type
Feature
Clarity
Needs clarification
Activity status
Active
Tech stack
javascript, nodejs
Domain
networking

Research direction

This is a governance proposal, not a code task: the work is to read GOVERNANCE.md and the decision-making process proposed in PR #5943, then leave review comments there. The open questions (WebSocket refable symbols in #5793, #5795, #5798; fetch tracing in #2701; the WebSocket frame cap in #5447; lazy Request/Response in #5415; body-mixin fast paths in #4349 and #5010) are for WG members to decide by vote, so a newcomer should not start a patch on them. Done means an informed comment on #5943, not a code change.

Written by the indexing model from the issue text.

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/undici on the issue or PR. This replaces the WG-agenda label 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 vote or 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.
  • Proposed compromise: standalone ref(websocket)/unref(websocket) helpers, similar to ping(websocket). My concern is that this would make process.ref(websocket) stop working and give undici an API no other Node.js object has.
  • Open PRs:
    • #5793 reverts the symbols. It has two change requests.
    • #5795 makes the symbols non-enumerable, and #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-polyfill for Node 18.
    • Tracing could go through undici's other APIs instead.
  • Counterpoint:
    • TracingChannel is 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-polyfill no 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 fetch harder to maintain.
    • Frameworks that need speed bypass these classes anyway.
  • Counterpoint:
    • The ecosystem is converging on Request/Response as 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.

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)
  • #4349 makes readAllBytes synchronous, which saves one promise per body read. It has two approvals and one change request.
  • #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 Uint8Array validation. 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: fetch is 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.

Dominant language
JavaScript
Stars
7.7k
Forks
931
Avg merge
3d 9h
Merged PRs (30d)
94

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from nodejs/undici

All issues in nodejs/undici

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.