You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
BroadcastChannel doesn't fill in useful MessageEvent fields like source, or ports #59053
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?
const util = require('util');
const channel = new BroadcastChannel('example');
if (isMainThread) {
channel.addEventListener('message', evt => {
console.log(util.inspect(evt)); // breakpoint here
});
} else {
channel.postMessage('hello');
}
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.
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
This 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.
@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.source for BroadcastChannel messages?
a sender threadId?
b something else?
What should event.ports contain in this context?
a transferred MessagePorts?
b remain empty for compatibility with current browser behavior?
Is the primary goal of this issue?
a alignment with the Web Platform semantics of MessageEvent, or
b enabling worker discovery and direct worker-to-worker communication patterns in Node.js?
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.
If exposing the sender's threadId via event.source would 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.
MessageEvent.source should remain unchanged, since for BroadcastChannel it 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(), and unref(), which should not necessarily be available to another Worker.
For Worker-to-Worker communication, postMessageToThread() already provides communication between threads based on the existing MessagePort infrastructure that can be used for direct inter-worker communication.
I think creating an extension for events of BroadcastChannel originating Worker to providing reliable lifecycle information might be helpful to address this issue
@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.
One problem with populating source is that it exposes native worker apis like terminate(), ref(), and unref() 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.
Activity
jdmarshall commentedon Jul 13, 2025
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.
jdmarshall commentedon Jul 13, 2025
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.
[-]BroadcastChannel doesn't fill in useful MessageEvent fields like origin, or ports[/-][+]BroadcastChannel doesn't fill in useful MessageEvent fields like source, or ports[/+]github-actions commentedon Apr 19, 2026
This 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.
jdmarshall commentedon Apr 22, 2026
Still would be useful.
SudhansuBandha commentedon Jun 10, 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
[] nullBased 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?
jdmarshall commentedon Jun 10, 2026
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.
SudhansuBandha commentedon Jun 11, 2026
We can reachout to maintainers for more clarity on this.
What information is expected to be exposed through
event.sourceforBroadcastChannelmessages?a sender
threadId?b something else?
What should
event.portscontain in this context?a transferred
MessagePorts?b remain empty for compatibility with current browser behavior?
Is the primary goal of this issue?
a alignment with the Web Platform semantics of
MessageEvent, orb enabling worker discovery and direct worker-to-worker communication patterns in Node.js?
@nodejs/workers
jdmarshall commentedon Jun 11, 2026
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.
aduh95 commentedon Jun 11, 2026
/cc @nodejs/workers
SudhansuBandha commentedon Jun 12, 2026
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.9 remaining items
SudhansuBandha commentedon Aug 20, 2026
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 issueworker: emit worker exit notifications on BroadcastChannel
worker: emit worker exit notifications on BroadcastChannel
worker: emit worker exit notifications on BroadcastChannel
SudhansuBandha commentedon Aug 27, 2026
@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.
jdmarshall commentedon Aug 27, 2026
That would help but I’m still curious why it’s difficult to emulate the browser API? Node isnt doing what Chrome already has.
SudhansuBandha commentedon Aug 27, 2026
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.jdmarshall commentedon Aug 27, 2026
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.worker: emit worker exit notifications on BroadcastChannel
worker: emit worker exit notifications on BroadcastChannel
worker: emit worker exit notifications on BroadcastChannel
worker: emit worker exit notifications on BroadcastChannel
worker: emit worker exit notifications on BroadcastChannel
worker: emit worker exit notifications on BroadcastChannel
worker: emit worker exit notifications on BroadcastChannel