What do you need to run BullMQ?
BullMQ is a queue library. Your app adds work to the queue, and a worker you run takes it off and executes it. The data store keeps the job and its status.
For the TypeScript package, the worker can run in Node.js or Bun. The default store is Redis. BullMQ v6 also supports PostgreSQL 13 or newer with the PostgreSQL client package. For that setup, create or update the queue tables as a separate deployment step before starting workers. You still need a worker that can stay running after the web request ends.
How do you test one queued report?
Connect a test producer, the code that adds the job, and a test worker to the same isolated queue.
- Confirm the test store and destinationsUse a test-only queue and worker credentials. Verify the worker reads fake records and writes only to the test file store. Leave live email, payments and repeating schedules disconnected before you add a job.
- Add one report and follow itUse a fake report ID. Watch the test job move from waiting to working and then completed. Close and reopen the test app while it runs and check that the report becomes available to the test account.
- Check the stored result after a repeatRepeat the same fake report request. Compare the queue history with the stored files. Your app should still show one usable report for that request.
Why can the same job run again?
BullMQ can retry a failed job when attempts are configured. A worker that stops reporting progress can also leave a job that returns to waiting or ends in failure.
Attempts count the first try as well as retries. Configure a delay for temporary failures and give persistent failures a visible final state. A worker may have finished an outside action before losing its place, so keep the actual report write safe to repeat.
A custom job ID can stop another copy from being added to the same queue while its record is still there. Once the job is removed, the same ID can be accepted again. Job IDs protect queue entry within that boundary. Use a durable result record or a stable key at the service that performs the action.
What controls when a job can start?
Worker capacity and queue-wide concurrency limit how many jobs run together. A scheduled job still waits for a worker.
The Job Scheduler creates the next occurrence when the last one starts. Under load, that can produce jobs less often than the requested interval. For a weekly report, track the week the report belongs to and whether it finished.
The library’s guide describes implementing a job timeout in your worker. Set a time boundary for outside requests and check that stopping a wait actually stops the work you expect. Monitor the host and database as well as the queue.
Where do you find a failed job?
Read the job state and worker logs. BullMQ exposes queue events so your app can record or alert on work that stopped.
The library can manually move a retained failed or completed job back to waiting. That starts the work again, so inspect the prior result and the safety of a repeat first.
Completed and failed jobs are kept by default. You can configure removal to limit store growth. Set retention long enough to investigate the failures you need, and keep customer results separately from queue history.
What does BullMQ cost and what do you operate?
The MIT-licensed library has no per-job subscription. Budget for the worker host, the queue’s database, storage, backups and monitoring.
The vendor sells a separate BullMQ Pro package. The library described here can run without it. The actual bill depends on how long and how many workers run and what your data store charges for memory, connections, storage and recovery.
For Redis, configure persistence and a memory policy that does not evict queue records. For PostgreSQL, check the schema permissions, connections, backups and restore plan. Keep a separate copy of your report records. Before moving, pause or drain the old worker as appropriate, account for waiting jobs and verify that resuming work will not produce a second result.