bullmq vs bull vs agenda vs bee-queue vs kue vs node-resque
Node.js Job Queue Libraries
bullmqbullagendabee-queuekuenode-resqueSimilar Packages:
Node.js Job Queue Libraries

agenda, bee-queue, bull, bullmq, kue, and node-resque are all Node.js libraries for managing background job queues — essential for offloading time-consuming tasks like sending emails, processing files, or syncing data. They enable reliable, asynchronous task execution with features like retries, delays, and failure handling. While they share the same goal, they differ significantly in architecture (MongoDB vs Redis), API design, maintenance status, and advanced capabilities like job prioritization or TypeScript support.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
bullmq2,465,9698,2422.27 MB3223 days agoMIT
bull1,116,64716,215309 kB147a year agoMIT
agenda138,6389,595353 kB355-MIT
bee-queue34,6854,006107 kB38a month agoMIT
kue16,6069,455-2889 years agoMIT
node-resque12,0381,408705 kB112 days agoApache-2.0

Choosing a Job Queue for Node.js: Agenda, Bee-Queue, Bull, BullMQ, Kue, and node-resque Compared

When you need to run background tasks in a Node.js application — like sending emails, processing images, or syncing data — you’ll likely reach for a job queue. The six packages compared here (agenda, bee-queue, bull, bullmq, kue, and node-resque) all solve this problem but with different trade-offs in architecture, features, and maintenance status. Let’s dive into how they differ and which one fits your needs.

⚠️ Deprecation Status: Don’t Start With These

Before comparing features, it’s critical to know that kue is officially deprecated. Its GitHub repository states: “Kue is no longer maintained.” You should not use kue in new projects. Similarly, while agenda and node-resque are still installable, their development has slowed significantly, and they lack modern features like TypeScript support or active issue triage.

That leaves bee-queue, bull, and bullmq as the actively maintained options worth serious consideration today.

🗄️ Data Store: Redis vs MongoDB

The biggest architectural split among these libraries is the underlying data store they require.

agenda and node-resque use MongoDB:

  • If your app already uses MongoDB and you want to avoid adding Redis, this might seem convenient.
  • But job queues benefit from Redis’s speed, atomic operations, and pub/sub model — MongoDB wasn’t built for this.
// agenda: Requires MongoDB connection
const agenda = new Agenda({ db: { address: 'mongodb://127.0.0.1/agendaDb' } });
agenda.define('send email', async (job) => {
  await sendEmail(job.attrs.data.to);
});
// node-resque: Also MongoDB-based
const worker = new NR.Worker({
  connection: { host: '127.0.0.1', port: 27017 },
  queues: ['email'],
  timeout: 5000
});

bee-queue, bull, and bullmq use Redis:

  • Redis is purpose-built for queues: fast, in-memory, with reliable persistence options.
  • All three assume you’re running Redis (locally or via a service like Upstash or AWS ElastiCache).
// bee-queue: Redis-backed
const Queue = require('bee-queue');
const emailQueue = new Queue('emails', { redis: { host: '127.0.0.1' } });
emailQueue.process(async (job) => {
  return await sendEmail(job.data.to);
});
// bull: Redis-backed
const Queue = require('bull');
const emailQueue = new Queue('emails'); // Uses default Redis connection
emailQueue.process(async (job) => {
  await sendEmail(job.data.to);
});
// bullmq: Redis-backed, TypeScript-native
import { Worker } from 'bullmq';
const worker = new Worker('emails', async (job) => {
  await sendEmail(job.data.to);
});

💡 Recommendation: Unless you have strong constraints against Redis, choose a Redis-based queue. It’s the industry standard for job queues.

🔁 Job Processing Model: Callbacks vs Async/Await

How you define and handle jobs varies significantly.

agenda and kue use callback-style APIs (though agenda supports async):

  • Feels dated compared to modern async/await patterns.
  • Error handling is more manual.
// kue (deprecated)
const q = require('kue').createQueue();
q.process('email', (job, done) => {
  sendEmail(job.data.to, (err) => {
    if (err) return done(err);
    done();
  });
});

bee-queue, bull, and bullmq fully embrace Promises and async/await:

  • Cleaner, more readable code.
  • Errors automatically fail the job unless caught.
// bull
queue.process('email', async (job) => {
  await sendEmail(job.data.to); // throws → job fails
});
// bullmq
new Worker('email', async (job) => {
  await sendEmail(job.data.to);
});

🧪 Advanced Features: Retries, Delays, Priorities

All modern queues support retries and delays, but implementation differs.

Retry strategies:

  • bull and bullmq let you configure backoff strategies (exponential, fixed).
  • bee-queue supports simple retry counts.
  • agenda supports retries but with less flexibility.
// bull: Exponential backoff
queue.add('work', { foo: 'bar' }, {
  attempts: 3,
  backoff: {
    type: 'exponential',
    delay: 1000
  }
});
// bullmq: Same concept, cleaner syntax
await queue.add('work', { foo: 'bar' }, {
  attempts: 3,
  backoff: {
    type: 'exponential',
    delay: 1000
  }
});
// bee-queue: Basic retries
queue.createJob({ foo: 'bar' })
  .retries(3)
  .save();

Job priorities:

  • Only bull and bullmq support job priorities out of the box.
  • Others require manual queue segregation (e.g., “high-priority” vs “low-priority” queues).
// bullmq: Priority support
await queue.add('work', { foo: 'bar' }, { priority: 1 }); // 1 = highest

📊 Monitoring and UI

Visibility into your queue health matters in production.

  • bull and bullmq integrate with Bull Board, a dashboard showing active, completed, and failed jobs.
  • agenda has third-party UIs like agenda-ui, but they’re less polished.
  • bee-queue has no official UI — you’d need to build your own monitoring.
  • kue had a built-in UI, but it’s obsolete now.
// bull board setup (for bull or bullmq)
import { createBullBoard } from '@bull-board/api';
import { BullAdapter } from '@bull-board/bull';

createBullBoard({
  queues: [new BullAdapter(myQueue)]
});

🧩 TypeScript Support

  • bullmq is written in TypeScript — full type safety out of the box.
  • bull has community-maintained types via @types/bull.
  • bee-queue, agenda, kue, and node-resque lack official TypeScript definitions.

If your project uses TypeScript, bullmq gives you the smoothest experience.

🔄 Migration Path: Bull to BullMQ

bullmq is the official successor to bull, built on the same core ideas but rewritten with TypeScript and improved internals. Key differences:

  • bull uses a single Queue class for both producing and consuming.
  • bullmq separates concerns: Queue (producer), Worker (consumer), QueueScheduler (optional for delayed jobs).
// bull: Single class
const queue = new Queue('work');
queue.process(async (job) => { /*...*/ });
queue.add('work', { data: 1 });
// bullmq: Separated roles
const queue = new Queue('work');
const worker = new Worker('work', async (job) => { /*...*/ });
await queue.add('work', { data: 1 });

This separation makes testing and scaling easier but adds slight verbosity.

🛑 Why Avoid the Deprecated Options?

kue

  • Officially deprecated — no security patches, bug fixes, or compatibility updates.
  • Callback-based API feels archaic.
  • No TypeScript support.
  • Built-in UI is unmaintained.

agenda

  • Still works but development has stalled (last significant commit was years ago).
  • MongoDB dependency limits performance and complicates ops.
  • Lacks modern features like priority queues or advanced backoff.

node-resque

  • Inspired by Ruby’s Resque, but not actively developed.
  • Minimal documentation and community support.
  • No TypeScript definitions.

✅ Real-World Recommendations

For New Projects

  • Choose bullmq if you want the most modern, well-maintained, TypeScript-friendly option with full feature parity (retries, priorities, delays, UI).
  • Choose bull if you’re migrating an existing codebase or prefer its simpler API and don’t need TypeScript.
  • Consider bee-queue only if you need a minimal, lightweight queue without priorities or complex UI — but know you’ll miss out on ecosystem tooling.

For Existing Projects

  • If you’re on bull, plan a migration to bullmq for long-term maintainability.
  • If you’re on agenda or kue, migrate to bullmq — the Redis switch is worth it for reliability and performance.

📌 Summary Table

PackageData StoreActively Maintained?TypeScriptPriority JobsBackoff StrategiesUI Available
agendaMongoDB❌ (Stale)LimitedThird-party
bee-queueRedisBasic
bullRedis✅ (via DT)✅ (Bull Board)
bullmqRedis✅ (Native)✅ (Bull Board)
kueRedis❌ (Deprecated)✅ (Obsolete)
node-resqueRedis❌ (Stale)

💡 Final Thought

Job queues are infrastructure — once you pick one, switching is painful. Go with bullmq for new work. It’s the future-proof choice that balances power, simplicity, and active maintenance. Avoid deprecated packages unless you’re maintaining legacy code with no upgrade path.

How to Choose: bullmq vs bull vs agenda vs bee-queue vs kue vs node-resque
  • bullmq:

    Choose bullmq for all new projects requiring a job queue. It's the actively maintained, TypeScript-native successor to bull, offering the same powerful features (priorities, advanced backoff, UI integration) with better architecture, type safety, and long-term support. It's the best balance of modern tooling and production readiness.

  • bull:

    Choose bull if you want a mature, Redis-based queue with a rich feature set (retries with backoff, priorities, delays) and good ecosystem support like Bull Board for monitoring. It's ideal for teams not yet using TypeScript or those migrating from older queue systems who want a stable, proven solution.

  • agenda:

    Choose agenda only if you're already deeply invested in MongoDB and cannot introduce Redis, and you're maintaining a legacy system where migration isn't feasible. Avoid it for new projects due to stalled development and lack of modern features like native TypeScript support or priority queues.

  • bee-queue:

    Choose bee-queue if you need a lightweight, Redis-based queue with a simple API and don't require advanced features like job priorities or a monitoring UI. It's suitable for small-to-medium applications where minimal dependencies and straightforward retry logic are sufficient.

  • kue:

    Do not choose kue for any new project — it is officially deprecated and no longer maintained. If you encounter it in legacy code, plan a migration to bullmq. Its callback-based API, lack of TypeScript support, and obsolete UI make it unsuitable for modern development.

  • node-resque:

    Avoid node-resque for new work. While it offers Redis-backed queuing inspired by Ruby's Resque, it suffers from minimal maintenance, poor documentation, and no TypeScript support. Only consider it if you're extending an existing system that already uses it and migration isn't possible.

README for bullmq



The fastest, most reliable, Redis-based distributed queue for Node.
Carefully written for rock solid stability and atomicity.

Read the documentation

Follow @manast for *important* Bull/BullMQ/BullMQ-Pro news and updates!

🛠 Tutorials

You can find tutorials and news in this blog: https://blog.taskforce.sh/

News 🚀

🌐 Language agnostic BullMQ

Do you need to work with BullMQ on platforms other than Node.js? If so, check out the BullMQ Proxy

Official FrontEnd

Taskforce.sh, Inc

Supercharge your queues with a professional front end:

  • Get a complete overview of all your queues.
  • Inspect jobs, search, retry, or promote delayed jobs.
  • Metrics and statistics.
  • and many more features.

Sign up at Taskforce.sh

🚀 Sponsors 🚀

Dragonfly Dragonfly is a new Redis™ drop-in replacement that is fully compatible with BullMQ and brings some important advantages over Redis™ such as massive better performance by utilizing all CPU cores available and faster and more memory efficient data structures. Read more here on how to use it with BullMQ.

Used by

Some notable organizations using BullMQ:

Microsoft Vendure Datawrapper Nest Langfuse
Curri Novu NoCodeDB Infisical

The gist

Install:

$ yarn add bullmq

Add jobs to the queue:

import { Queue } from 'bullmq';

const queue = new Queue('Paint');

queue.add('cars', { color: 'blue' });

Process the jobs in your workers:

import { Worker } from 'bullmq';

const worker = new Worker('Paint', async job => {
  if (job.name === 'cars') {
    await paintCar(job.data.color);
  }
});

Listen to jobs for completion:

import { QueueEvents } from 'bullmq';

const queueEvents = new QueueEvents('Paint');

queueEvents.on('completed', ({ jobId }) => {
  console.log('done painting');
});

queueEvents.on(
  'failed',
  ({ jobId, failedReason }: { jobId: string; failedReason: string }) => {
    console.error('error painting', failedReason);
  },
);

Adds jobs with parent-child relationship:

import { FlowProducer } from 'bullmq';

const flow = new FlowProducer();

const originalTree = await flow.add({
  name: 'root-job',
  queueName: 'topQueueName',
  data: {},
  children: [
    {
      name: 'child-job',
      data: { idx: 0, foo: 'bar' },
      queueName: 'childrenQueueName',
      children: [
        {
          name: 'grandchild-job',
          data: { idx: 1, foo: 'bah' },
          queueName: 'grandChildrenQueueName',
        },
        {
          name: 'grandchild-job',
          data: { idx: 2, foo: 'baz' },
          queueName: 'grandChildrenQueueName',
        },
      ],
    },
    {
      name: 'child-job',
      data: { idx: 3, foo: 'foo' },
      queueName: 'childrenQueueName',
    },
  ],
});

This is just scratching the surface, check all the features and more in the official documentation

Feature Comparison

Since there are a few job queue solutions, here is a table comparing them:

FeatureBullMQ-ProBullMQBullKueBeeAgenda
Backendredisredisredisredisredismongo
Observables
Group Rate Limit
Group Support
Batches Support
Parent/Child Dependencies
Deduplication (Debouncing)
Deduplication (Throttling)
Priorities
Concurrency
Delayed jobs
Global events
Rate Limiter
Pause/Resume
Sandboxed worker
Repeatable jobs
Atomic ops
Persistence
UI
Optimized forJobs / MessagesJobs / MessagesJobs / MessagesJobsMessagesJobs

Contributing

Fork the repo, make some changes, submit a pull-request! Here is the contributing doc that has more details.

Thanks

Thanks for all the contributors that made this library possible, also a special mention to Leon van Kammen that kindly donated his npm bullmq repo.