agenda vs bee-queue vs bull vs bullmq vs kue
Job and Queue Management
agendabee-queuebullbullmqkueSimilar Packages:

Job and Queue Management

Job and queue management libraries in Node.js provide tools for handling background tasks, scheduling jobs, and managing queues of tasks to be processed asynchronously. These libraries help improve application performance by offloading time-consuming tasks from the main event loop, allowing for better resource utilization and responsiveness. They often include features like job prioritization, retries, scheduling, and monitoring, making them suitable for a wide range of applications, from simple task processing to complex workflows. bull and bullmq are popular libraries that offer robust queue management with Redis integration, while agenda focuses on job scheduling with a MongoDB backend. bee-queue is a lightweight and simple queue library, and kue provides a feature-rich solution with a web interface for monitoring jobs.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
agenda09,651297 kB27 days agoMIT
bee-queue04,027107 kB464 months agoMIT
bull016,243309 kB149a year agoMIT
bullmq08,7052.45 MB3627 hours agoMIT
kue09,459-2889 years agoMIT

Feature Comparison: agenda vs bee-queue vs bull vs bullmq vs kue

Storage Backend

  • agenda:

    agenda uses MongoDB as its storage backend, which allows for persistent job storage, making it suitable for long-running applications where job data needs to be retained across restarts.

  • bee-queue:

    bee-queue uses Redis as its storage backend, but it is designed to be lightweight and does not persist job data to disk, making it more suitable for ephemeral job processing where durability is not a primary concern.

  • bull:

    bull uses Redis for job storage, providing durability and persistence. It supports features like job retries, delayed jobs, and prioritization, making it suitable for production-grade applications that require reliable job processing.

  • bullmq:

    bullmq also uses Redis but is designed with a more modern architecture, offering better performance and scalability. It supports advanced features like rate limiting, job events, and a more flexible data model, making it ideal for large-scale applications.

  • kue:

    kue uses Redis for job storage and provides a web interface for monitoring jobs. It supports job prioritization, retries, and failure handling, making it suitable for applications that require a visual representation of job processing.

Job Scheduling

  • agenda:

    agenda supports job scheduling with features like recurring jobs, delayed jobs, and one-time jobs. It provides a flexible API for defining job schedules and supports time zone handling.

  • bee-queue:

    bee-queue does not natively support job scheduling or recurring jobs. It focuses on simple job queuing and processing, making it lightweight but limited in scheduling capabilities.

  • bull:

    bull supports delayed jobs and job prioritization, but it does not have built-in support for recurring jobs. However, it can be extended to handle scheduled jobs with additional logic.

  • bullmq:

    bullmq supports delayed jobs and job scheduling, with a more flexible and efficient design compared to bull. It allows for better handling of scheduled jobs and provides more control over job execution.

  • kue:

    kue supports job scheduling with delayed jobs and prioritization. It allows for more complex job management, including retries and failure handling, making it suitable for applications that require more control over job execution.

Monitoring and UI

  • agenda:

    agenda does not provide a built-in UI for monitoring jobs. However, it integrates well with third-party tools and can be extended to provide monitoring features.

  • bee-queue:

    bee-queue does not have a built-in UI, but it is designed to be simple and lightweight, allowing developers to build custom monitoring tools if needed.

  • bull:

    bull provides a built-in UI for monitoring job queues, including job status, retries, and failures. It is user-friendly and helps developers and operators monitor job processing in real-time.

  • bullmq:

    bullmq offers an improved UI for monitoring job queues, with better visualization and control over jobs. It is designed to be more modular and extensible, allowing for custom integrations and monitoring solutions.

  • kue:

    kue provides a feature-rich web interface for monitoring jobs, including job status, retries, and failures. It is one of the standout features of kue, making it easy to manage and visualize job processing.

Performance and Scalability

  • agenda:

    agenda is suitable for moderate workloads and can scale horizontally by adding more instances. However, its performance is heavily dependent on the MongoDB setup and indexing.

  • bee-queue:

    bee-queue is designed for high performance with low memory usage, making it suitable for processing a large number of jobs quickly. However, it may not scale well for very large or complex job workflows.

  • bull:

    bull is highly performant and scalable, capable of handling a large number of jobs with Redis as the backend. It supports horizontal scaling by adding more worker instances, making it suitable for production environments.

  • bullmq:

    bullmq is designed for better performance and scalability compared to bull, with a more efficient data model and support for advanced features like rate limiting and job events. It is ideal for large-scale applications that require high throughput and resource efficiency.

  • kue:

    kue is performant for moderate workloads but may encounter scalability issues with very high job volumes. It is suitable for applications that require reliable job processing but may need optimization for large-scale use.

Ease of Use: Code Examples

  • agenda:

    Simple job scheduling with agenda

    const Agenda = require('agenda');
    const mongoConnectionString = 'mongodb://localhost:27017/agenda';
    const agenda = new Agenda({ db: { address: mongoConnectionString } });
    
    // Define a job
    agenda.define('send email', async (job) => {
      console.log('Sending email...');
    });
    
    // Schedule a job
    agenda.schedule('in 1 minute', 'send email');
    
    // Start the agenda
    agenda.start();
    
  • bee-queue:

    Simple job queue with bee-queue

    const Queue = require('bee-queue');
    const queue = new Queue('my-queue');
    
    // Process jobs
    queue.process(async (job) => {
      console.log(`Processing job ${job.id}: ${job.data}`);
    });
    
    // Add a job
    queue.add({ message: 'Hello, world!' });
    
  • bull:

    Job queue with bull

    const Queue = require('bull');
    const myQueue = new Queue('my-queue');
    
    // Process jobs
    myQueue.process(async (job) => {
      console.log(`Processing job ${job.id}: ${job.data}`);
    });
    
    // Add a job
    myQueue.add({ message: 'Hello, Bull!' });
    
  • bullmq:

    Job queue with bullmq

    const { Queue } = require('bullmq');
    const queue = new Queue('my-queue');
    
    // Process jobs
    queue.process(async (job) => {
      console.log(`Processing job ${job.id}: ${job.data}`);
    });
    
    // Add a job
    queue.add('my-job', { message: 'Hello, BullMQ!' });
    
  • kue:

    Job queue with kue

    const kue = require('kue');
    const queue = kue.createQueue();
    
    // Process jobs
    queue.process('email', (job, done) => {
      console.log(`Processing job ${job.id}: ${job.data}`);
      done();
    });
    
    // Add a job
    const job = queue.create('email', { to: 'example@example.com' }).save();
    

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

  • agenda:

    Choose agenda if you need a job scheduler that integrates with MongoDB and supports recurring jobs, delayed jobs, and job prioritization. It is ideal for applications that require flexible scheduling and persistence of job data.

  • bee-queue:

    Choose bee-queue if you need a simple and lightweight queue system with a focus on performance and low memory usage. It is suitable for applications that require fast job processing with minimal overhead and does not need advanced features like job prioritization or retries.

  • bull:

    Choose bull if you need a feature-rich queue system with Redis support, offering advanced features like job retries, prioritization, delayed jobs, and a built-in UI for monitoring. It is suitable for applications that require robust queue management and scalability.

  • bullmq:

    Choose bullmq if you need a modern, modular, and more efficient version of bull with improved performance and a redesigned API. It is ideal for applications that require advanced queueing features and better resource management, especially for large-scale systems.

  • kue:

    Choose kue if you need a job queue library with a built-in web interface for monitoring jobs, along with support for job prioritization, retries, and failure handling. It is suitable for applications that require a visual representation of job processing and easy management of jobs.

README for agenda

Agenda

Agenda

A light-weight job scheduling library for Node.js

NPM Version NPM Downloads

Migrating from v5? See the Migration Guide for all breaking changes.

Agenda 6.x

Agenda 6.x is a complete TypeScript rewrite with a focus on modularity and flexibility:

  • Pluggable storage backends - Choose from MongoDB, PostgreSQL, Redis, or implement your own. Each backend is a separate package - install only what you need.

  • Pluggable notification channels - Move beyond polling with real-time job notifications via Redis, PostgreSQL LISTEN/NOTIFY, or other pub/sub systems. Jobs get processed immediately when saved, not on the next poll cycle.

  • Modern stack - ESM-only, Node.js 18+, full TypeScript with strict typing.

See the 6.x Roadmap for details and progress.

Features

  • Minimal overhead job scheduling
  • Pluggable storage backends (MongoDB, PostgreSQL, Redis)
  • TypeScript support with full typing
  • Scheduling via cron or human-readable syntax
  • Configurable concurrency and locking
  • Real-time job notifications (optional)
  • Sandboxed worker execution via fork mode
  • TypeScript decorators for class-based job definitions

Installation

Install the core package and your preferred backend:

# For MongoDB
npm install agenda @agendajs/mongo-backend

# For PostgreSQL
npm install agenda @agendajs/postgres-backend

# For Redis
npm install agenda @agendajs/redis-backend

Requirements:

  • Node.js 18+
  • Database of your choice (MongoDB 4+, PostgreSQL, or Redis)

Quick Start

import { Agenda } from 'agenda';
import { MongoBackend } from '@agendajs/mongo-backend';

const agenda = new Agenda({
  backend: new MongoBackend({ address: 'mongodb://localhost/agenda' })
});

// Define a job
agenda.define('send email', async (job) => {
  const { to, subject } = job.attrs.data;
  await sendEmail(to, subject);
});

// Start processing
await agenda.start();

// Schedule jobs
await agenda.every('1 hour', 'send email', { to: 'user@example.com', subject: 'Hello' });
await agenda.schedule('in 5 minutes', 'send email', { to: 'admin@example.com', subject: 'Report' });
await agenda.now('send email', { to: 'support@example.com', subject: 'Urgent' });

Official Backend Packages

PackageBackendNotificationsInstall
@agendajs/mongo-backendMongoDBPolling onlynpm install @agendajs/mongo-backend
@agendajs/postgres-backendPostgreSQLLISTEN/NOTIFYnpm install @agendajs/postgres-backend
@agendajs/redis-backendRedisPub/Subnpm install @agendajs/redis-backend

Backend Capabilities

BackendStorageNotificationsNotes
MongoDB (MongoBackend)Storage only. Combine with external notification channel for real-time.
PostgreSQL (PostgresBackend)Full backend. Uses LISTEN/NOTIFY for notifications.
Redis (RedisBackend)Full backend. Uses Pub/Sub for notifications.
InMemoryNotificationChannelNotifications only. For single-process/testing.

Backend Configuration

MongoDB

import { Agenda } from 'agenda';
import { MongoBackend } from '@agendajs/mongo-backend';

// Via connection string
const agenda = new Agenda({
  backend: new MongoBackend({ address: 'mongodb://localhost/agenda' })
});

// Via existing MongoDB connection
const agenda = new Agenda({
  backend: new MongoBackend({ mongo: existingDb })
});

// With options
const agenda = new Agenda({
  backend: new MongoBackend({
    mongo: db,
    collection: 'jobs'        // Collection name (default: 'agendaJobs')
  }),
  processEvery: '30 seconds', // Job polling interval
  maxConcurrency: 20,         // Max concurrent jobs
  defaultConcurrency: 5       // Default per job type
});

PostgreSQL

import { Agenda } from 'agenda';
import { PostgresBackend } from '@agendajs/postgres-backend';

const agenda = new Agenda({
  backend: new PostgresBackend({
    connectionString: 'postgresql://user:pass@localhost:5432/mydb'
  })
});

Redis

import { Agenda } from 'agenda';
import { RedisBackend } from '@agendajs/redis-backend';

const agenda = new Agenda({
  backend: new RedisBackend({
    connectionString: 'redis://localhost:6379'
  })
});

Real-Time Notifications

For faster job processing across distributed systems:

import { Agenda, InMemoryNotificationChannel } from 'agenda';
import { MongoBackend } from '@agendajs/mongo-backend';

const agenda = new Agenda({
  backend: new MongoBackend({ mongo: db }),
  notificationChannel: new InMemoryNotificationChannel()
});

Mixing Storage and Notification Backends

You can use MongoDB for storage while using a different system for real-time notifications:

import { Agenda } from 'agenda';
import { MongoBackend } from '@agendajs/mongo-backend';
import { RedisBackend } from '@agendajs/redis-backend';

// MongoDB for storage + Redis for real-time notifications
const redisBackend = new RedisBackend({ connectionString: 'redis://localhost:6379' });
const agenda = new Agenda({
  backend: new MongoBackend({ mongo: db }),
  notificationChannel: redisBackend.notificationChannel
});

This is useful when you want MongoDB's proven durability and flexible queries for job storage, but need faster real-time notifications across multiple processes.

API Overview

Defining Jobs

// Simple async handler
agenda.define('my-job', async (job) => {
  console.log('Processing:', job.attrs.data);
});

// With options
agenda.define('my-job', async (job) => { /* ... */ }, {
  concurrency: 10,
  lockLimit: 5,
  lockLifetime: 10 * 60 * 1000, // 10 minutes
  priority: 'high'
});

Defining Jobs with Decorators

For a class-based approach, use TypeScript decorators:

import { JobsController, Define, Every, registerJobs, Job } from 'agenda';

@JobsController({ namespace: 'email' })
class EmailJobs {
  @Define({ concurrency: 5 })
  async sendWelcome(job: Job<{ userId: string }>) {
    console.log('Sending welcome to:', job.attrs.data.userId);
  }

  @Every('1 hour')
  async cleanupBounced(job: Job) {
    console.log('Cleaning up bounced emails');
  }
}

registerJobs(agenda, [new EmailJobs()]);
await agenda.start();

// Schedule using namespaced name
await agenda.now('email.sendWelcome', { userId: '123' });

See Decorators Documentation for full details.

Scheduling Jobs

// Run immediately
await agenda.now('my-job', { userId: '123' });

// Run at specific time
await agenda.schedule('tomorrow at noon', 'my-job', data);
await agenda.schedule(new Date('2024-12-25'), 'my-job', data);

// Run repeatedly
await agenda.every('5 minutes', 'my-job');
await agenda.every('0 * * * *', 'my-job'); // Cron syntax

Job Control

// Cancel jobs matching a filter (removes from database)
await agenda.cancel({ name: 'my-job' });
await agenda.cancel({ name: 'my-job', data: { userId: 123 } });

// Cancel ALL jobs unconditionally
await agenda.cancelAll();

// Disable/enable jobs globally (by query)
await agenda.disable({ name: 'my-job' });  // Disable all jobs matching query
await agenda.enable({ name: 'my-job' });   // Enable all jobs matching query

// Disable/enable individual jobs
const job = await agenda.create('my-job', data);
job.disable();
await job.save();

// Progress tracking
agenda.define('long-job', async (job) => {
  for (let i = 0; i <= 100; i += 10) {
    await doWork();
    await job.touch(i); // Report progress 0-100
  }
});

Stopping / Draining

// Stop immediately - unlocks running jobs so other workers can pick them up
await agenda.stop();

// Drain - waits for running jobs to complete before stopping
await agenda.drain();

// Drain with timeout (30 seconds) - for cloud platforms with shutdown deadlines
const result = await agenda.drain(30000);
if (result.timedOut) {
    console.log(`${result.running} jobs still running after timeout`);
}

// Drain with AbortSignal - for external control
const controller = new AbortController();
setTimeout(() => controller.abort(), 30000);
await agenda.drain({ signal: controller.signal });

Use drain() for graceful shutdowns where you want in-progress jobs to finish their work.

Events

agenda.on('start', (job) => console.log('Job started:', job.attrs.name));
agenda.on('complete', (job) => console.log('Job completed:', job.attrs.name));
agenda.on('success', (job) => console.log('Job succeeded:', job.attrs.name));
agenda.on('fail', (err, job) => console.log('Job failed:', job.attrs.name, err));

// Job-specific events
agenda.on('start:send email', (job) => { /* ... */ });
agenda.on('fail:send email', (err, job) => { /* ... */ });

Custom Backend

For databases other than MongoDB, PostgreSQL, or Redis, implement AgendaBackend:

import { AgendaBackend, JobRepository } from 'agenda';

class SQLiteBackend implements AgendaBackend {
  readonly repository: JobRepository;
  readonly notificationChannel = undefined; // Or implement NotificationChannel

  async connect() { /* ... */ }
  async disconnect() { /* ... */ }
}

const agenda = new Agenda({
  backend: new SQLiteBackend({ path: './jobs.db' })
});

See Custom Backend Driver for details.

Documentation

Related Packages

Official Backend Packages:

Tools:

License

MIT