Repository navigation
BroadcastChannel doesn't fill in useful MessageEvent fields like source, or ports #59053
Description
Activity
I believe if this were weaved into the active work on https://nodejs.org/api/worker_threads.html#workerpostmessagetothreadthreadid-value-transferlist-timeout
it would make that feature much more powerful, because BroadcastChannels could then be used to coordinate discovery and then private messagePorts could be established between workers that need them.
Implementing the fields defined by https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel/message_event
Would likely negate the need for the postMessageToThread() functionality entirely. You just need a shared presence BroadcastChannel to allow workers that need to talk to each other to be introduced, instead of messaging threadIds at random.
- changed the title
[-]BroadcastChannel doesn't fill in useful MessageEvent fields like origin, or ports[/-][+]BroadcastChannel doesn't fill in useful MessageEvent fields like source, or ports[/+]on Jul 13, 2025 - addedworkerIssues and PRs related to the worker_threads module and Worker API.Issues and PRs related to the worker_threads module and Worker API.
on Jul 22, 2025 github-actions commented
on Apr 19, 2026 on Apr 19, 2026 – with GitHub ActionsContributorMore actionsThis issue has been marked as stale due to 210 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.- addedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Apr 19, 2026 Still would be useful.
- removedstaleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.Issues and PRs marked stale due to inactivity and scheduled for automatic closure.
on Apr 23, 2026 @jdmarshall if we try to run these additional lines of code in your provided sample
console.log(evt.ports); console.log(evt.source);
then the output is
[] null
Based on this it looks like these fields are already available to use. May I know is there any specific implementation whitch is not present atm apart from missing fields as described that will address this issue?Based on this it looks like these fields are already available to use.
I don't understand how the absence of information equates to being 'available to use'. You have to populate a field in order for the field to be useful. There is no data propagation going on which makes it difficult for one worker to find another. It's not really a broadcast channel by the usual definition of broadcast if all data must come from and return to the main thread. That's just a multiplexed channel. Broadcast would be 2 classes of workers being able to talk to each other. Which would require information such as the source to be populated so a response could be formulated.
We can reachout to maintainers for more clarity on this.
What information is expected to be exposed through
event.sourceforBroadcastChannelmessages?
a senderthreadId?
b something else?What should
event.portscontain in this context?
a transferredMessagePorts?
b remain empty for compatibility with current browser behavior?Is the primary goal of this issue?
a alignment with the Web Platform semantics ofMessageEvent, or
b enabling worker discovery and direct worker-to-worker communication patterns in Node.js?@nodejs/workers
TL;DR: Populate the source field.
It's been a real minute and I need to look around to see if I still have my test case anywhere.
I understand why event.ports is tricky, because for ports to be shared the broadcast mechanism would have to have been built down at the port level. You can't have 5 workers writing to the same port. But there's not a way to sendMessage to a particular worker because that information is not there, which is why the postMessageToThread functionality is presumably being worked on which is not great, one reason being is that finding the threadId is still problematic, so you have to use the broadcast channel to do rendezvous anyway. Using three APIs to accomplish a task two should be able to do is messy.
What I have is one worker aggregating data to send out over a socket. Data aggregation of that sort and volume needs to be evicted from the main thread so that the amount of time the event loop blocks is not proportional to the number of workers. That screws up vertical scaling substantially, and P99 times will show massive intermittent spikes, which could trigger alarms. No good. I'm thinking particularly of telemetry data, but any system architecture that uses heterogenous workers in order to avoid cooperative multitasking's limitations with latency tails will run into this problem.
So what I would prefer is that when a worker starts, it uses the BroadcastChannel only to perform a rendezvous to exchange ports between the sender and the receiver. I am here, send me a port for this class of traffic, got it, let's rock. Then the peers don't need to hear traffic intended for each other, except the rendezvous which should be very, very infrequent. But the missing fields prevent that from happening.
/cc @nodejs/workers
If exposing the sender's
threadIdviaevent.sourcewould address the use case, I'd be interested in exploring a PR for it (along with appropriate tests), assuming this approach aligns with the intended design and maintainers are open to it.8 remaining items
I'm going to change the summary for this story a bit because the ask I'm making has much bigger implications than I think I have communicated. There's a giant hole in the middle of the Worker API specification and I believe this change fills in most of that hole, while lesser solutions do essentially nothing to fill it in. Which is why I'm being particular about how I'd like it to be fixed.
MessageEvent.sourceshould remain unchanged, since forBroadcastChannelit is expected to be null under the web platform semantics.Exposing the actual Worker object through source could also unintentionally expose APIs such as
terminate(),ref(), andunref(), which should not necessarily be available to another Worker.For Worker-to-Worker communication,
postMessageToThread() already provides communication between threads based on the existingMessagePortinfrastructure that can be used for direct inter-worker communication.I think creating an extension for events of
BroadcastChanneloriginating Worker to providing reliable lifecycle information might be helpful to address this issueReacted by Jason Marshall@jdmarshall PTAL at this PR. I have created this setup to emit events which get triggered when worker exits in a Broadcast Channel. I know this might not solve all the lifecycle events tracking but hopefully this can be a good start based on which we can make further progress.
That would help but I’m still curious why it’s difficult to emulate the browser API? Node isnt doing what Chrome already has.
One problem with populating source is that it exposes native worker apis like
terminate(),ref(), andunref()to other threads which can lead to termination of source worker by another worker. That is something which should not be allowed.I don't know if I agree with that. We are all running in the same sandbox, employed by the same bosses. The security guarantee is if you do something egregious you lose your job, not a VM enforcing security constraints.
I can always just call
process.exit(0)in main and kill the entire VM.- added a commit that references this issue
on Aug 27, 2026 - added a commit that references this issue
on Sep 3, 2026 - added a commit that references this issue
on Sep 18, 2026
Please populate the Worker value in BroadcastChannel MessageEvents 'source' field the same way it is in WebWorkers.
There is currently no mechanism to compose Workers in the NodeJS APIs and this change would provide a mechanism to
solve that problem, if not for the general case, at least with only a small amount of additional bookkeeping on the part of
application developers.
Without a composition mechanism, it is extremely difficult to implement cross-cutting concerns between workers, and between workers and large subsystems in the main application. Which is problematic for many areas of production code including caching, telemetry, reloadable configuration, and security.
Fundamentally, there is no mechanism to tell if a Worker has terminated. And since Workers tend to be used for tasks with high utilization of the event toop, even sending a message to ask if anyone is still listening to the BroadcastChannel is not guaranteed to work on any reasonable time frame, and in particular for cross-cutting concerns who can't know what, for instance, the cutoff time is for image processing in the Image Worker, and that the Cache Worker has a cutoff of 1/100th of that time. Which then leads to a scenario where you've decided a Worker is dead and then the same worker pops back up 10 seconds later. What you need is
worker.on('exit')which is unambiguous.Version
All versions
Platform
All Platforms
Subsystem
node:worker_threads
What steps will reproduce the bug?
The Message Event recieved looks like
How often does it reproduce? Is there a required condition?
Always. Seems to be by design, and the design may have drifted from the current web standards over time.
What is the expected behavior? Why is that the expected behavior?
That I get a Worker object to facilitate lifecycle management and IPC coordination.
What do you see instead?
empty string, empty array. And no other mechanism in the Node API to interrogate the running isolates to find this information.
Additional information
No response