Skip to content

BroadcastChannel doesn't fill in useful MessageEvent fields like source, or ports #59053

Description

@jdmarshall

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');
        }

The Message Event recieved looks like


MessageEvent {
  type: 'message',
  defaultPrevented: false,
  cancelable: false,
  timeStamp: 444.018666
}

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

Activity

  1. jdmarshall commented on Jul 13, 2025

    @jdmarshall
    Author

    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.

  2. jdmarshall commented on Jul 13, 2025

    @jdmarshall
    Author

    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.

  3. 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
  4. added
    workerIssues and PRs related to the worker_threads module and Worker API.
    on Jul 22, 2025
  5. github-actions commented on Apr 19, 2026

    @github-actions
    Contributor

    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.

  6. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Apr 19, 2026
  7. jdmarshall commented on Apr 22, 2026

    @jdmarshall
    Author

    Still would be useful.

  8. removed
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Apr 23, 2026
  9. SudhansuBandha commented on Jun 10, 2026

    @SudhansuBandha
    Contributor

    @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?

  10. jdmarshall commented on Jun 10, 2026

    @jdmarshall
    Author

    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.

  11. SudhansuBandha commented on Jun 11, 2026

    @SudhansuBandha
    Contributor

    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?

    @nodejs/workers

  12. jdmarshall commented on Jun 11, 2026

    @jdmarshall
    Author

    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.

  13. aduh95 commented on Jun 11, 2026

    @aduh95
    Contributor

    /cc @nodejs/workers

  14. SudhansuBandha commented on Jun 12, 2026

    @SudhansuBandha
    Contributor

    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.

  15. 8 remaining items

  16. jdmarshall commented on Aug 12, 2026

    @jdmarshall
    Author

    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.

  17. SudhansuBandha commented on Aug 20, 2026

    @SudhansuBandha
    Contributor

    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

  18. SudhansuBandha commented on Aug 27, 2026

    @SudhansuBandha
    Contributor

    @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.

  19. jdmarshall commented on Aug 27, 2026

    @jdmarshall
    Author

    That would help but I’m still curious why it’s difficult to emulate the browser API? Node isnt doing what Chrome already has.

  20. SudhansuBandha commented on Aug 27, 2026

    @SudhansuBandha
    Contributor

    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.

  21. jdmarshall commented on Aug 27, 2026

    @jdmarshall
    Author

    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.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    workerIssues and PRs related to the worker_threads module and Worker API.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions