Sunday, July 12, 2026

Announcing BullMQ for Rust

Cover for Announcing BullMQ for Rust

We are thrilled to announce that BullMQ is now available for Rust. The Rust community can now use one of the most popular Redis-backed job queue systems through a native, asynchronous implementation designed for production workloads.

The first stable release (1.0.0) is published on crates.io as bullmq-official and can be added to any project with a single command:

cargo add bullmq-official

BullMQ for Rust is implemented natively with async/await and tokio, giving Rust developers an idiomatic API while retaining the reliability and semantics that BullMQ users expect.

The comprehensive BullMQ for Rust guide covers installation, core concepts and practical examples for queues, workers, jobs and the other components introduced in this release.

Built natively for Rust

The API follows familiar Rust conventions. Operations are asynchronous, errors use Result, processors are safe to share between tasks, and workers take advantage of Tokio's multi-threaded runtime. A queue and worker can be created in just a few lines:

use bullmq::worker::{CancellationToken, ProcessorFn};
use bullmq::{Job, Queue, QueueOptions, Worker, WorkerOptions};
use std::sync::Arc;

#[tokio::main]
async fn main() -> bullmq::Result<()> {
let queue = Queue::new("email", QueueOptions::default()).await?;

queue.add("send-email", serde_json::json!({
"to": "user@example.com",
"subject": "Hello from Rust"
}), None).await?;

let processor: ProcessorFn = Arc::new(|job: Job, _token: CancellationToken| {
Box::pin(async move {
println!("Processing job {}", job.id());
Ok(serde_json::json!({ "sent": true }))
})
});

let worker = Worker::new("email", processor, WorkerOptions::default()).await?;

tokio::signal::ctrl_c()
.await
.expect("failed to listen for Ctrl+C");
worker.close(5000).await?;
Ok(())
}

The package is published as bullmq-official because the most obvious crate names were already taken, but it is imported naturally in code as bullmq.

This first stable release already includes the vast majority of what applications need to run background jobs in production:

  • Queue supports delayed and prioritized jobs, deduplication, custom IDs, global concurrency and rate limits, metrics and rich queue inspection.
  • Worker provides configurable concurrency, retries, backoff, lock renewal, stalled-job detection, rate limiting and cancellation.
  • Job exposes progress tracking, logs, lifecycle controls and parent/child relationships.
  • FlowProducer atomically creates trees of dependent jobs.
  • QueueEvents observes job lifecycle events across processes through Redis Streams.
  • JobScheduler supports cron and interval-based recurring jobs.

Although the Rust API is new, the queue semantics at its core are not. BullMQ for Rust executes the exact same Lua scripts as the battle-tested Node.js, Python, PHP and Elixir implementations. These scripts handle critical state transitions such as claiming, completing, retrying and moving jobs, and have already been exercised extensively in production. As a result, the Rust release starts with a very strong foundation for stability rather than reimplementing BullMQ's most sensitive logic from scratch.

The public API is also Send + Sync and designed to be FFI-friendly, making this implementation a potential foundation for bindings to other languages. You can find the remaining differences from the Node.js implementation in the feature-parity document.

Competitive performance from day one

Node.js has been BullMQ's battle-tested reference implementation for years, so it provides a demanding and meaningful baseline for the new Rust implementation. We wanted the first stable Rust release not only to offer the right API and feature set, but also to demonstrate competitive throughput from day one.

We ran bullmq-official and the bullmq 5.80 npm package through the same scenarios against the same local Redis instance. Processing throughput was measured at steady state, excluding one-off worker startup and connection costs. The high-concurrency test used 200,000 jobs over multiple runs to reduce noise.

The results below were measured on an Apple M2 Pro (12 cores), with Redis 7.2 on localhost, Node.js 22 and Rust 1.85+. Numbers are throughput in jobs per second (higher is better):

Scenario Node.js (bullmq 5.80) Rust (bullmq-official)
Add — sequential (1k, await each) ~5,400 ~6,900
Add — parallel (100k, batches of 1k) ~54,000 ~54,000
Bulk add (5k, single addBulk) ~34,000 ~38,000
Process — concurrency 10 (5k jobs) ~18,600 ~19,600
Process — concurrency 100 (200k jobs) ~27,000 ~27,000

Rust is slightly ahead for sequential and bulk ingestion, effectively tied for highly parallel ingestion, and on par with Node.js for processing. Both implementations complete a job and fetch the next one in a single Redis round-trip by letting the moveToFinished Lua script return the next job to process. At very high concurrency Node.js showed somewhat lower run-to-run variance, while both reached the same peak throughput.

This is a strong starting point for the Rust implementation: it is already competitive with the reference package across both job ingestion and processing. There is still room to optimize connection usage and internal worker bookkeeping in future releases, particularly at very high concurrency. As always, results will vary with hardware, Redis deployment, network latency and the work performed by each job.

Interoperability with the BullMQ ecosystem

Although this release is primarily about bringing a mature queue system to the Rust community, interoperability remains an important benefit. BullMQ for Rust uses the same Redis data structures and the exact same Lua scripts as the Node.js, Python, PHP and Elixir implementations.

Jobs produced in Rust can therefore be processed in any of those languages, and Rust workers can consume jobs they produce. Queue state, flows and lifecycle events are shared without an adapter layer, a sidecar process or a data migration. This makes it possible to adopt Rust incrementally for performance-sensitive services while keeping existing BullMQ infrastructure in place.

Try it out

BullMQ for Rust is available today from crates.io:

cargo add bullmq-official

There are two complementary documentation resources:

The source lives alongside the other implementations in the main BullMQ repository. Keeping the implementations together makes it easier to evolve their shared scripts and compatibility guarantees in lockstep.

We are excited to see what the Rust community builds with BullMQ. If you run into anything or have suggestions, please open an issue on GitHub. Happy queueing, now natively in Rust!