Skip to content
Get started
Get started
bunqueue vs BullMQ Benchmark: Redis 8.10.2, BullMQ 6.4.2
View Markdown
guide · benchmark

bunqueue vs BullMQ, measured.

bunqueue 2.9.20 against BullMQ 6.4.2 on Redis 8.10.2, on one machine with pinned cores, 5 measured runs per number and an exact-delivery check on every run. Where each one is faster, and by how much.

Measured October 25, 2026. Every table cell is the median of 5 runs after one warm-up run, with the range of the 5 runs in parentheses. BullMQ runs on both Node.js and Bun, and each ratio compares bunqueue with the faster of the two. Pickup-latency and delayed-job rows use bunqueue with pollTimeout: 5000, the long-poll mode BullMQ workers use by default; every other bunqueue row uses its defaults.

CPUAMD Ryzen 9 7950X3D, 16 cores / 32 threads, up to 5.76 GHz, 128 MiB L3 (two CCDs)
Memory124 GiB
Disk3x Samsung PM9A3 NVMe (MZQL21T9HCJR) in RAID 5, ext4
SystemDebian GNU/Linux 13 (trixie), Linux 6.12.48+deb13-amd64, bare metal, CPU governor performance
Pinningbroker on CPUs 2,3,18,19 (two physical cores), clients on 8-15,24-31 (the other CCD)
Conditionsa shared server: other services ran during the run, so each cell reports the median of five runs with its range
bunqueue2.9.20 (npm), server started with bunqueue start, clients from bunqueue/client on Bun 1.4.4
BullMQ6.4.2 with ioredis 6.0.0, on Node.js 24.22.1 and on Bun 1.4.4
Redis8.10.2, official Docker image, host networking
  • One broker at a time, Redis or the bunqueue server, pinned to the same two physical cores. Producers and workers run in separate processes on the other core complex, so the broker never shares a core or a cache with its clients.
  • Both libraries use their documented defaults, plus removeOnComplete and removeOnFail on every job. The bunqueue server runs with RATE_LIMIT_WINDOW_MS=0: its per-connection request limit protects a shared server and Redis has no equivalent.
  • Every run uses a fresh client process and a new queue. Every consuming run checks that each accepted job was processed exactly once (three times in the retry scenario); a run that loses or duplicates a job fails instead of reporting a number.
  • Pickup latency comes from an open-loop producer at a fixed rate and is measured from each job’s scheduled send time, so a broker that falls behind shows up as latency rather than as a lower offered load.
  • In memory: bunqueue’s in-memory engine against Redis without persistence. Durable: bunqueue on SQLite (WAL) against Redis with AOF and appendfsync everysec, both on the same disk.
ScenariobunqueueBullMQ on Node.jsBullMQ on Bunbunqueue vs best BullMQ
Add jobs one at a time (jobs/s)28,890 (27,036–29,538)19,450 (18,927–19,534)22,730 (22,366–23,231)1.27x
Add jobs, 64 in flight (jobs/s)202,072 (198,734–219,865)68,094 (67,780–70,096)77,692 (75,974–79,439)2.60x
Add jobs in bulk (100 per call) (jobs/s)207,601 (186,591–217,414)47,831 (47,232–48,015)52,503 (51,567–53,303)3.95x
Process a backlog, 1 worker process (jobs/s)43,335 (43,240–45,233)38,402 (38,314–38,429)38,262 (38,171–38,306)1.13x
Process a backlog, 4 worker processes (jobs/s)53,754 (52,417–53,920)40,699 (40,653–40,714)39,879 (39,837–40,653)1.32x
Process a backlog, 8 worker processes (jobs/s)42,408 (41,534–42,429)39,873 (39,856–39,874)39,830 (39,814–39,857)1.06x
Pickup latency p50 at 1,000 jobs/s (ms, lower is better)0.65 ms (0.64–0.65)0.78 ms (0.78–0.78)0.70 ms (0.70–0.71)1.09x
Pickup latency p99 at 1,000 jobs/s (ms, lower is better)1.18 ms (1.18–1.19)1.35 ms (1.35–1.36)1.25 ms (1.25–1.25)1.06x
Pickup latency p50 at 5,000 jobs/s (ms, lower is better)0.81 ms (0.80–0.82)1.02 ms (1.01–1.03)0.88 ms (0.88–0.88)1.08x
Pickup latency p99 at 5,000 jobs/s (ms, lower is better)2.68 ms (2.50–2.96)1.56 ms (1.55–1.57)1.37 ms (1.36–1.38)BullMQ 1.96x
Pickup latency p50 at 10,000 jobs/s (ms, lower is better)0.94 ms (0.93–0.94)1.41 ms (1.40–1.41)1.14 ms (1.14–1.14)1.22x
Pickup latency p99 at 10,000 jobs/s (ms, lower is better)4.29 ms (4.10–5.11)2.22 ms (2.21–2.24)1.84 ms (1.80–1.87)BullMQ 2.33x
Delayed job lateness p50 (ms, lower is better)4.74 ms (4.54–4.86)40.5 ms (40.2–40.6)41.0 ms (40.9–41.5)8.54x
Delayed job lateness p99 (ms, lower is better)13.1 ms (12.9–13.7)83.1 ms (82.9–83.4)83.7 ms (83.3–84.0)6.34x
Retries (fail twice, succeed on the third attempt) (jobs/s)7,119 (7,118–7,129)4,243 (4,192–4,284)5,536 (5,392–5,544)1.29x

bunqueue ahead (1.1x or more):

  • Add jobs one at a time: 1.27x
  • Add jobs, 64 in flight: 2.60x
  • Add jobs in bulk (100 per call): 3.95x
  • Process a backlog, 1 worker process: 1.13x
  • Process a backlog, 4 worker processes: 1.32x
  • Pickup latency p50 at 10,000 jobs/s: 1.22x
  • Delayed job lateness p50: 8.54x
  • Delayed job lateness p99: 6.34x
  • Retries (fail twice, succeed on the third attempt): 1.29x

Level (within 10%):

  • Process a backlog, 8 worker processes: 1.06x
  • Pickup latency p50 at 1,000 jobs/s: 1.09x
  • Pickup latency p99 at 1,000 jobs/s: 1.06x
  • Pickup latency p50 at 5,000 jobs/s: 1.08x

BullMQ ahead:

  • Pickup latency p99 at 5,000 jobs/s: BullMQ 1.96x
  • Pickup latency p99 at 10,000 jobs/s: BullMQ 2.33x
ScenariobunqueueBullMQ on Node.jsBullMQ on Bunbunqueue vs best BullMQ
Add jobs one at a time (jobs/s)9,000 (8,924–9,016)17,785 (17,661–18,065)20,316 (19,738–20,920)BullMQ 2.26x
Add jobs, 64 in flight (jobs/s)31,773 (31,044–33,009)62,238 (61,957–62,672)63,431 (63,234–63,880)BullMQ 2.00x
Add jobs in bulk (100 per call) (jobs/s)41,913 (41,137–42,482)40,762 (40,464–40,966)44,285 (43,834–45,235)BullMQ 1.06x
Process a backlog, 1 worker process (jobs/s)4,946 (4,874–5,150)32,201 (32,180–32,226)31,114 (31,070–32,136)BullMQ 6.51x
Process a backlog, 4 worker processes (jobs/s)4,491 (4,451–4,521)33,242 (33,225–33,260)33,219 (33,216–33,259)BullMQ 7.40x
Process a backlog, 8 worker processes (jobs/s)4,257 (4,234–4,288)33,233 (32,716–33,240)33,215 (33,196–33,240)BullMQ 7.81x
Pickup latency p50 at 1,000 jobs/s (ms, lower is better)0.97 ms (0.97–0.98)0.80 ms (0.78–0.80)0.72 ms (0.71–0.72)BullMQ 1.36x
Pickup latency p99 at 1,000 jobs/s (ms, lower is better)5.72 ms (5.67–5.78)1.38 ms (1.34–1.38)1.27 ms (1.27–1.28)BullMQ 4.50x
Pickup latency p50 at 5,000 jobs/s (ms, lower is better)1612 ms (1579–1618)1.11 ms (1.09–1.11)0.92 ms (0.92–0.92)BullMQ 1,746x
Pickup latency p99 at 5,000 jobs/s (ms, lower is better)3590 ms (3548–3669)1.65 ms (1.65–1.68)1.46 ms (1.44–1.46)BullMQ 2,465x
Pickup latency p50 at 10,000 jobs/s (ms, lower is better)13117 ms (13021–13183)1.56 ms (1.55–1.58)1.24 ms (1.23–1.24)BullMQ 10,604x
Pickup latency p99 at 10,000 jobs/s (ms, lower is better)22910 ms (22784–22959)2.77 ms (2.74–2.96)2.70 ms (2.62–2.96)BullMQ 8,476x
Delayed job lateness p50 (ms, lower is better)644 ms (623–666)39.2 ms (39.0–39.5)39.5 ms (39.3–39.5)BullMQ 16.4x
Delayed job lateness p99 (ms, lower is better)1181 ms (1151–1221)82.0 ms (81.7–82.7)81.6 ms (81.0–81.9)BullMQ 14.5x
Retries (fail twice, succeed on the third attempt) (jobs/s)809 (806–819)4,074 (4,047–4,141)4,985 (4,978–4,989)BullMQ 6.16x

On SQLite, bunqueue processes about 4,946 jobs/s with one worker process. At 5,000 and 10,000 jobs/s the offered load is above that, so the backlog grows for the whole 15-second run and the pickup-latency rows measure how far behind the queue fell, not a steady-state latency.

The disk matters for this mode. This server’s disk is a RAID 5 array of three NVMe drives. In a diagnostic single run on the same server (one worker process, 50,000 jobs), the one-process drain reached 6,165 jobs/s with the SQLite file on that disk and 11,332 jobs/s with it in RAM (/dev/shm): the disk explains about half of the gap, and Redis with AOF everysec stays ahead even then. Redis appends to its log and syncs once a second; bunqueue’s SQLite engine writes each completed job, with synchronous = NORMAL in WAL mode.

bunqueue ahead (1.1x or more):

  • none

Level (within 10%):

  • Add jobs in bulk (100 per call): BullMQ 1.06x

BullMQ ahead:

  • Add jobs one at a time: BullMQ 2.26x
  • Add jobs, 64 in flight: BullMQ 2.00x
  • Process a backlog, 1 worker process: BullMQ 6.51x
  • Process a backlog, 4 worker processes: BullMQ 7.40x
  • Process a backlog, 8 worker processes: BullMQ 7.81x
  • Pickup latency p50 at 1,000 jobs/s: BullMQ 1.36x
  • Pickup latency p99 at 1,000 jobs/s: BullMQ 4.50x
  • Pickup latency p50 at 5,000 jobs/s: BullMQ 1,746x
  • Pickup latency p99 at 5,000 jobs/s: BullMQ 2,465x
  • Pickup latency p50 at 10,000 jobs/s: BullMQ 10,604x
  • Pickup latency p99 at 10,000 jobs/s: BullMQ 8,476x
  • Delayed job lateness p50: BullMQ 16.4x
  • Delayed job lateness p99: BullMQ 14.5x
  • Retries (fail twice, succeed on the third attempt): BullMQ 6.16x

Broker memory with a 1,000,000-job backlog

Section titled “Broker memory with a 1,000,000-job backlog”
Modebunqueue idlebunqueue with 1M jobsRedis idleRedis with 1M jobs
In memory46 MiB2252 MiB24 MiB618 MiB
Durable49 MiB2415 MiB24 MiB583 MiB

Resident memory of the broker process (bunqueue) or used_memory_rss (Redis), read after the backlog was added.

The harness, its pinned versions and the raw results of this run are in bench/vs-bullmq in the repository:

cd bench/vs-bullmq
bun install --frozen-lockfile
bun src/run.ts

It needs Linux, Docker, Bun, Node.js and taskset, and takes about 70 minutes. Results land in results/<timestamp>/: every run, the medians, and the hardware, kernel and package versions. The comparison guide covers features and when BullMQ is the better choice.