Quick Start
INFO
This guide uses the TypeScript package, which runs on Node.js and Bun. If you are using another language, check the getting started section of the Python, Elixir, .NET, Rust or PHP SDKs. All of them can work on the same queues.
Install
Install using npm:
$ npm install bullmqInstall using yarn:
$ yarn add bullmqInstall using pnpm:
$ pnpm add bullmqInstall using Bun:
$ bun add bullmqINFO
BullMQ is written in TypeScript, and although it can be used in vanilla JavaScript, all examples in this guide will be written in TypeScript.
Start a datastore
BullMQ stores its queues in Redis™ by default, so you need a Redis 6.2+ (or compatible, such as Valkey or Dragonfly) server running. The quickest way to get one locally is with Docker:
$ docker run -d --name redis -p 6379:6379 redis:latestIf you would rather use PostgreSQL, see Using PostgreSQL below.
Add jobs and process them
Import into your project and add some jobs:
import { Queue } from 'bullmq';
const myQueue = new Queue('foo');
async function addJobs() {
await myQueue.add('myJobName', { foo: 'bar' });
await myQueue.add('myJobName', { qux: 'baz' });
}
await addJobs();DANGER
When no connection options are given, BullMQ connects to Redis on localhost:6379, so you need a Redis service running in your local computer to run these examples successfully. You can read more about connections, including other Redis clients such as node-redis, Bun's Redis client or Valkey GLIDE, here.
Jobs are added to the queue and can be processed at any time, by at least one worker. Workers can run in the same process as the queue or in any other process or machine, and they can even be written in a different language:
import { Worker } from 'bullmq';
import IORedis from 'ioredis';
const connection = new IORedis({ maxRetriesPerRequest: null });
const worker = new Worker(
'foo',
async job => {
// Will print { foo: 'bar'} for the first job
// and { qux: 'baz' } for the second.
console.log(job.data);
},
{ connection },
);INFO
You can have as many worker processes as you want, BullMQ will distribute the jobs across your workers in a round robin fashion.
You can listen to completed (or failed) jobs by attaching listeners to the workers:
worker.on('completed', job => {
console.log(`${job.id} has completed!`);
});
worker.on('failed', (job, err) => {
console.log(`${job.id} has failed with ${err.message}`);
});INFO
There are many other events available, check the Guide or the API reference for more information.
Sometimes you need to listen to all the workers events in a given place, for this you need to use a special class QueueEvents:
import { QueueEvents } from 'bullmq';
const queueEvents = new QueueEvents('my-queue-name');
queueEvents.on('waiting', ({ jobId }) => {
console.log(`A job with ID ${jobId} is waiting`);
});
queueEvents.on('active', ({ jobId, prev }) => {
console.log(`Job ${jobId} is now active; previous status was ${prev}`);
});
queueEvents.on('completed', ({ jobId, returnvalue }) => {
console.log(`${jobId} has completed and returned ${returnvalue}`);
});
queueEvents.on('failed', ({ jobId, failedReason }) => {
console.log(`${jobId} has failed with reason ${failedReason}`);
});You may also access the timestamp of the event, which looks like "1580456039332-0".
import { QueueEvents } from 'bullmq';
const queueEvents = new QueueEvents('my-queue-name');
queueEvents.on('progress', ({ jobId, data }, timestamp) => {
console.log(`${jobId} reported progress ${data} at ${timestamp}`);
});DANGER
For performance reasons, the events emitted by a QueueEvents instance do not contain the Job instance, only the jobId. Use the Job.fromId method if you need the Job instance.
Using PostgreSQL
The same API runs on PostgreSQL 13 or newer. In TypeScript, install the pg package, apply BullMQ's schema migrations once (for example as a deployment step), and pass the createPostgresBackend factory as the last constructor argument. The Python, Elixir and .NET SDKs apply the migrations automatically on first use (see their introduction pages for the PostgreSQL driver they require):
$ npm install pgimport { Pool } from 'pg';
import { Queue, Worker, createPostgresBackend, runMigrations } from 'bullmq';
const connection = 'postgres://postgres:postgres@localhost:5432/mydb';
// Run once, for example in a deployment step.
const pool = new Pool({ connectionString: connection });
const client = await pool.connect();
try {
await runMigrations(client);
} finally {
client.release();
await pool.end();
}
const queue = new Queue('foo', { connection }, createPostgresBackend);
await queue.add('myJobName', { foo: 'bar' });
const worker = new Worker(
'foo',
async job => {
console.log(job.data);
},
{ connection },
createPostgresBackend,
);from bullmq import Queue, Worker
connection = "postgres://postgres:postgres@localhost:5432/mydb"
# Migrations are applied automatically on first use.
queue = Queue("foo", {"backend": "postgres", "connection": connection})
await queue.add("myJobName", {"foo": "bar"})
async def process(job, token):
print(job.data)
worker = Worker("foo", process, {"backend": "postgres", "connection": connection})# Migrations are applied automatically when the connection starts.
{:ok, _pid} =
BullMQ.Backends.Postgres.Connection.start_link(
name: :my_pg,
url: "postgres://postgres:postgres@localhost:5432/mydb"
)
{:ok, _job} =
BullMQ.Queue.add("foo", "myJobName", %{foo: "bar"},
connection: :my_pg,
backend: BullMQ.Backends.Postgres
)
{:ok, _worker} =
BullMQ.Worker.start_link(
queue: "foo",
connection: :my_pg,
backend: BullMQ.Backends.Postgres,
processor: fn job ->
IO.inspect(job.data)
:ok
end
)using BullMQ;
using BullMQ.Postgres;
var postgres = new PostgresOptions
{
ConnectionString = "Host=localhost;Port=5432;Database=mydb;Username=postgres;Password=postgres",
};
// Migrations are applied automatically on first use.
await using var queue = new Queue("foo", new QueueOptions { Postgres = postgres });
await queue.AddAsync("myJobName", new { foo = "bar" });
await using var worker = new Worker(
"foo",
async (job, cancellationToken) =>
{
Console.WriteLine(job.Data);
return null;
},
new WorkerOptions { Postgres = postgres });
await worker.RunAsync();Read more in the PostgreSQL backend section.
Next steps
- Learn the main concepts in the Guide.
- Prepare your deployment with Going to production.
- Find out how BullMQ works internally in Architecture.