
BullMQ
The Node.js job queue on Redis, Bull’s successor, with ports to other languages and, since v6, a Postgres backend.
- What it is
- Message queues
- Type
- Open source
- Made by
- Taskforce.sh (BullForce Labs AB)
- License
- MIT (BullMQ Pro is commercial)
- Facts checked
- 6 October 2026
What it is
BullMQ is a library, not a server. A Queue object in your app adds jobs, and Worker objects in your own processes pick them up; all the state lives in Redis 6.2 or newer, or a compatible server. A job moves between states (waiting, prioritized, delayed, active, completed, failed), and each change runs as a Lua script inside Redis, so it stays atomic with many workers. A worker holds a lock on each active job and keeps renewing it. If the lock lapses, because the process died or blocked the event loop too long, the job is “stalled” and goes back to waiting, or to failed after too many stalls. On top come retries with fixed or exponential backoff, delays, priorities, rate limits, deduplication, cron-style job schedulers and parent and child jobs (“flows”) across queues.
The core is MIT-licensed and developed by Taskforce.sh; Manuel Astudillo, who wrote the earlier Bull library, started it. It’s native to Node.js and Bun, with ports for Python, Elixir, .NET and Rust that share queues with Node.js, and a PHP client that can only add jobs. BullMQ 6 (July 2026) made storage pluggable and added a PostgreSQL backend with the same API, which its docs put at roughly 1.5 to 2 times fewer processed jobs a second than Redis. BullMQ Pro adds groups, batches and observables for Node.js and Bun under a commercial licence: $1,395 a year or $139 a month per deployment for organizations with fewer than 100 employees, and custom pricing above that (checked October 2026).
Why teams pick it
- A mature feature set: retries with backoff, delays, priorities, rate limiting, deduplication, job schedulers and parent and child flows
- Runs on Redis, Valkey and Dragonfly (all three tested in CI), managed services such as ElastiCache and MemoryDB, and since v6 on PostgreSQL
- Queues are shared across languages: Node.js, Python, Elixir, .NET and Rust workers, plus PHP producers
- Fast: its site cites over 250,000 jobs a second in benchmarks on Dragonfly
- Sandboxed processors run CPU-heavy jobs in separate processes, and graceful shutdown and stalled-job recovery are built in
Watch out for
- Redis must use
maxmemory-policy noeviction; a cache-style eviction policy breaks queues, and ElastiCache Serverless can’t be set that way - Completed and failed jobs stay in Redis by default; without
removeOnCompleteandremoveOnFail, memory keeps filling - A handler that blocks Node’s event loop can’t renew its lock, so the job stalls and runs again on another worker
- Groups (per-tenant fairness), batches and observables need the paid Pro edition, for Node.js and Bun only
- Ports aren’t equal: PHP can only add jobs and Python was introduced as experimental; v6 removed legacy repeatable jobs and Redis internals, so upgrading needs code changes
Alternatives
What all message queues have in common →
Amazon SQSAWSAWS’s fully managed message queue: no brokers to run, billed per request.How it fits with other technologies
Add a job with retries, process it, and log failures · ts
import { Queue, Worker } from 'bullmq';
import IORedis from 'ioredis';
const connection = new IORedis({ maxRetriesPerRequest: null });
const thumbnails = new Queue('thumbnails', { connection });
await thumbnails.add(
'resize',
{ key: 'uploads/123.jpg', width: 320 },
{ attempts: 5, backoff: { type: 'exponential', delay: 1000 } },
);
const worker = new Worker(
'thumbnails',
async job => {
await resize(job.data.key, job.data.width);
return { done: true };
},
{ connection, concurrency: 10, removeOnComplete: { count: 1000 } },
);
worker.on('failed', (job, err) => console.error(job?.id, err.message));Where BullMQ can keep its queues#
The API is the same everywhere; what changes is the setting you have to get right.
| Backend | Status | What to watch |
|---|---|---|
| Redis 6.2+ | Default backend | Set maxmemory-policy to noeviction |
| Valkey | Tested in CI against Valkey 8 | Also works through the Valkey Glide client adapter |
| Dragonfly | Tested in CI; listed as officially supported | Wrap queue names in {} so each queue gets its own thread |
| Amazon ElastiCache | Documented | Node-based clusters only; Serverless uses an incompatible eviction policy |
| Amazon MemoryDB | Documented | Cluster mode only, so put hash tags in queue names |
| PostgreSQL 13+ | Since v6.0 (July 2026) | LISTEN/NOTIFY replaces blocking pops; about 1.5 to 2 times fewer jobs a second than Redis |
Bull, BullMQ and BullMQ Pro#
| Bull | BullMQ | BullMQ Pro | |
|---|---|---|---|
| Status | Maintenance mode: bug fixes only | Actively developed | Actively developed |
| Licence and price | MIT, free | MIT, free | Commercial: $1,395 a year or $139 a month per deployment (under 100 employees); custom above |
| Languages | Node.js | Node.js and Bun, plus Python, Elixir, .NET, Rust and PHP clients | Node.js and Bun |
| Parent and child flows | No | Yes | Yes |
| Groups, batches, observables | No | No | Yes |
- A deployment is one operational environment, such as a Kubernetes cluster, server or VM, connecting to one or more Redis instances. Prices from bullmq.io, checked 2026-10-06.
See it in a real stack
No architecture uses BullMQ yet. Drop it into the playground and wire it up yourself.Open playground →Where it came from2013–2026
In June 2013 Manuel Astudillo of OptimalBits started Bull, a job queue for Node.js that kept its state in Redis and leaned on Redis’s atomic operations. It sat alongside libraries such as Kue and Bee, and Redis’s own guide to queues later picked Bull as its Node.js example.
In December 2018 Astudillo began BullMQ, a rewrite in TypeScript, under the taskforcesh organization on GitHub; 1.0 shipped in October 2019. Bull went into maintenance mode, fixing only bugs. The business around it is Taskforce.sh, which sells a hosted dashboard for queues and BullMQ Pro, a commercial edition with groups, batches and observables, while the core stays MIT.
BullMQ then stopped being only a Node.js library. A Python package appeared in 2023, Elixir and PHP clients in December 2025, and Rust and .NET in mid-2026, all reading and writing the same queues. BullMQ 6, in July 2026, hid Redis behind a backend interface and added PostgreSQL, so the same code can run on a database many teams already operate.
Why it’s built this way
- Lua scripts for every state change
- Moving a job between states touches several Redis keys. Running each move as a script inside Redis makes it atomic without locks in the application, so many workers can share one queue safely.
- A library, not a server
- Queues and workers are objects in your own processes, and Redis holds the state, so there’s nothing extra to deploy. Other platforms can reach queues through the separate BullMQ Proxy.
- Renewable locks on active jobs
- A worker that dies can’t release its jobs, so each lock must be renewed periodically. A lapsed lock marks the job stalled and returns it to the queue.
- An MIT core with a paid Pro edition
- Pro features such as groups and batches, plus support, fund development, while the main library stays free with no limits on workers or concurrency.
Timeline
- 2013
Manuel Astudillo starts Bull at OptimalBits
- 2018
BullMQ, a TypeScript rewrite, begins in December
- 2019
BullMQ 1.0 released in October
- 2023
First Python package (0.1) released
- 2025
Elixir and PHP clients reach first releases
- 2026
BullMQ 6 adds pluggable backends and PostgreSQL
- Bull: initial commit by Manuel Astudillo (Jun 2013)
- BullMQ: initial commit by Manuel Astudillo (Dec 2018)
- Bull README: maintenance mode
- BullMQ changelog v1 (1.0.0, Oct 2019)
- BullMQ Python changelog v0 (0.1.0, Feb 2023)
- BullMQ Elixir changelog v1 (1.0.0, Dec 2025)
- BullMQ PHP changelog v1 (0.1.0, Dec 2025)
- BullMQ Rust changelog (1.0.0, Jul 2026)
- BullMQ .NET changelog (1.0.0, Aug 2026)
- Redis glossary: Redis queue (Bull as the Node.js example)
- BullMQ changelog (6.0.0, Jul 2026)
Sources20 · facts checked 6 October 2026
- BullMQ README
- BullMQ home page (backends, benchmarks, Pro pricing)
- BullMQ docs: Architecture
- BullMQ docs: Connections (ioredis, node-redis, Bun, Valkey Glide)
- BullMQ docs: Going to production (noeviction)
- BullMQ docs: Stalled jobs
- BullMQ docs: Retrying failing jobs
- BullMQ docs: Auto-removal of jobs
- BullMQ docs: Sandboxed processors
- BullMQ docs: Graceful shutdown
- BullMQ docs: PostgreSQL backend
- BullMQ docs: Redis compatibility
- BullMQ docs: Dragonfly
- BullMQ docs: AWS ElastiCache
- BullMQ docs: AWS MemoryDB
- BullMQ docs: PHP introduction (producer only)
- BullMQ docs: Python introduction
- BullMQ CI workflow (Redis, Valkey 8, Dragonfly, PostgreSQL)
- BullMQ LICENSE (MIT, BullForce Labs AB)
- Dragonfly docs: BullMQ integration