Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstalliTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Use BullMQ’s QueueEvents when one or more services need to observe job lifecycle events across every worker handling a queue. Workers distribute jobs among themselves; they do not each receive a copy. For cross-worker visibility without adding another broker, give each observing service its own QueueEvents instance connected to Redis.
What “fan-out” means in BullMQ
BullMQ separates job processing from event observation. A Worker consumes and processes jobs from a shared queue. Multiple workers can share that work, but a job is not copied to every worker. A worker’s ordinary event listeners are local to that worker’s process, so they are not a queue-wide feed.
QueueEvents provides that queue-wide observation point. It is implemented with Redis Streams, which BullMQ documents as providing delivery guarantees across listener disconnections that standard pub/sub does not. Each independent service that needs to observe events should create its own QueueEvents instance and register handlers for the event types it needs. Within one process, an instance can dispatch events to several callbacks.
Recommended Free Tools
Set up a QueueEvents listener
- Create the listener: import
QueueEventsfrombullmqand construct it with the queue name and the application’s Redis connection. - Register event handlers: listen for the lifecycle events the service needs, such as
completed,failed, orprogress. - Wait until it is ready: call
waitUntilReady()before relying on the listener. - Close it at shutdown: call
close()so the listener releases its Redis connection.
import { QueueEvents } from 'bullmq';
const queueEvents = new QueueEvents('orders', { connection });
queueEvents.on('completed', ({ jobId, returnvalue }) => {
notifyConsumers({ type: 'completed', jobId, returnvalue });
});
queueEvents.on('failed', ({ jobId, failedReason }) => {
notifyConsumers({ type: 'failed', jobId, failedReason });
});
await queueEvents.waitUntilReady();
// During application shutdown:
await queueEvents.close();
This is an illustrative TypeScript pattern based on BullMQ’s documented API, not a tested implementation. Adapt the connection configuration and the event fields to the installed BullMQ version and your application.
#1 Best Overall
Choose the right event scope and payload
| Approach | What it observes | What the handler receives | When it fits |
|---|---|---|---|
| Worker event listener | Events local to the worker process that completed the job | Worker-local event data, which can include the job object depending on the event | Logic that belongs to that worker’s own processing lifecycle |
QueueEvents |
Lifecycle events at queue scope, across workers | Compact event fields, commonly including jobId and fields such as returnvalue, failedReason, or progress data; not a hydrated Job object |
Dashboards, notifications, or other services that need queue-wide visibility |
Because QueueEvents payloads are lightweight, retrieve the job by its ID only when the observer genuinely needs the full object. BullMQ’s quick start describes fetching a job with Job.fromId as an option. Avoid assuming that an event contains every property available on a Job.
Account for retention and Redis
BullMQ automatically trims the QueueEvents stream to approximately 10,000 events by default, according to its current Events guide, accessed in 2026. The maximum can be changed with streams.events.maxLen. Choose a retention limit with expected event volume and plausible listener downtime in mind: a stream trimmed while a consumer is disconnected cannot serve as an unlimited historical event archive.
Rank #2
Redis is still required. BullMQ stores jobs in Redis, and its quick start requires a running Redis service. QueueEvents avoids introducing a separate broker for this observation pattern; it does not remove BullMQ’s Redis dependency.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Use custom events when lifecycle events are not enough
If observers need application-defined event names rather than job lifecycle changes, BullMQ documents QueueEventsProducer for publishing custom events that QueueEvents consumers can subscribe to. That extends the event vocabulary; it does not change the distinction between observing an event and distributing a separate copy of each job to every consumer.
Rank #3
Handle errors and distinguish observation from business delivery
Attach appropriate error handlers to workers and listeners. BullMQ warns that an unhandled worker error can stop processing. Treat queue events as lifecycle observations for services such as dashboards or notifications; BullMQ’s documentation does not present QueueEvents as a replacement for a separately designed durable business-event system.
If every independent consumer must process its own copy of every work item, QueueEvents is not that mechanism. Design explicit job fan-out so each consumer has work to process; use QueueEvents when the requirement is to observe what happened to jobs across workers.
Quick Recap
Best Value
Rank #4
Documentation
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

