Background jobs for Elixir

An Elixir port of BullMQ built with GenServers and Supervisors. It runs on Redis or PostgreSQL and can share queues with Node.js.

{:bullmq, "~> 1.0"}

Elixir / OTP ยท Redis 6.2+ (or Valkey/Dragonfly) or PostgreSQL 13+ (via postgrex)

Your first queue and worker

my_queue.ex
{:ok, job} = BullMQ.Queue.add(
"Paint", "cars", %{color: "blue"},
connection: :redis,
delay: 30_000
)
my_worker.ex
defmodule MyWorker do
def process(%BullMQ.Job{name: "cars", data: data}) do
paint_car(data["color"])
{:ok, %{painted: true}}
end
end

{:ok, _worker} = BullMQ.Worker.start_link(
queue: "Paint",
connection: :redis,
processor: &MyWorker.process/1,
concurrency: 100
)

The same job handling as the Node.js library

All BullMQ libraries run the same Lua scripts on Redis and the same SQL on PostgreSQL, so jobs are handled the same way in every language. Only the API around those scripts differs from one library to the next.

More Elixir examples

Common BullMQ features, written in Elixir.

Global events

events.ex
# Events via Worker callbacks
{:ok, _worker} = BullMQ.Worker.start_link(
queue: "Paint",
connection: :redis,
processor: &MyWorker.process/1,
on_completed: fn job, result ->
IO.puts("Job #{job.id} completed")
end,
on_failed: fn job, reason ->
IO.puts("Job #{job.id} failed")
end
)

Repeatable jobs

repeatable.ex
# Repeat job once every day at 3:15 (am)
{:ok, job} = BullMQ.Queue.add(
"Paint", "submarine", %{color: "yellow"},
connection: :redis,
repeat: %{pattern: "* 15 3 * * *"}
)

Rate limiting

ratelimit.ex
{:ok, _worker} = BullMQ.Worker.start_link(
queue: "Paint",
connection: :redis,
processor: fn job -> paint_car(job); {:ok, nil} end,
limiter: %{max: 10, duration: 1000}
)

Retries & backoff

retry.ex
{:ok, job} = BullMQ.Queue.add(
"Paint", "car", %{color: "pink"},
connection: :redis,
attempts: 3,
backoff: %{type: :exponential, delay: 1000}
)

Flows

flow.ex
{:ok, job} = BullMQ.FlowProducer.add(
%{
name: "Renovate",
queue_name: "cars",
children: [
%{name: "paint", queue_name: "steps"},
%{name: "engine", queue_name: "steps"},
%{name: "wheels", queue_name: "steps"}
]
},
connection: :redis
)

Using BullMQ with Elixir

Built on OTP

Queues and workers are GenServers, so you add them to your supervision tree like any other process.

Redis or PostgreSQL

Use Redis, or use PostgreSQL through postgrex if that is the database you already run.

Telemetry

BullMQ emits Telemetry events, which you can send to the metrics and dashboards you already use.

Node.js Elixir

One queue, any language

Elixir and Node.js workers can process jobs from the same queue, so you can move to Elixir one service at a time.

What's available in Elixir

  • Add jobs to queues Supported
  • Process jobs (workers) Supported
  • Delayed jobs Supported
  • Repeatable / scheduled jobs Supported
  • Job priorities Supported
  • Rate limiting Supported
  • Retries & backoff Supported
  • Flows (parent / child) Supported
  • Job events Supported
  • Redis backend Supported
  • PostgreSQL backend Supported
  • BullMQ Pro Coming soon

BullMQ Pro for Elixir Coming soon

BullMQ Pro adds groups, observables and batches to the open source library. It is available for Node.js and Bun today, and support for Elixir is on the way.

Groups
Observables
Batches

Get started with BullMQ for Elixir