agenda vs bree vs bull vs cron vs later vs node-cron vs node-schedule
Node.js Task Scheduling Libraries
agendabreebullcronlaternode-cronnode-scheduleSimilar Packages:

Node.js Task Scheduling Libraries

Task scheduling libraries in Node.js are essential for automating repetitive tasks, managing background jobs, and executing code at specific intervals. These libraries provide developers with the tools to schedule tasks efficiently, ensuring that operations such as sending emails, processing data, or cleaning up resources occur at predetermined times or intervals. Each library offers unique features and capabilities, making it important to choose the right one based on project requirements and complexity.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
agenda09,652295 kB2a month agoMIT
bree03,28492 kB29a month agoMIT
bull016,245309 kB147a year agoMIT
cron08,916161 kB264 months agoMIT
later02,418-9810 years agoMIT
node-cron03,249221 kB349 months agoISC
node-schedule09,22135 kB1713 years agoMIT

Feature Comparison: agenda vs bree vs bull vs cron vs later vs node-cron vs node-schedule

Storage

  • agenda:

    Agenda stores scheduled jobs in MongoDB, allowing for persistence and easy management of jobs across application restarts. This makes it suitable for long-running applications that need to maintain job states.

  • bree:

    Bree does not require persistent storage, as it uses worker threads to execute jobs in memory. This approach is efficient for short-lived tasks that do not need to be stored between executions.

  • bull:

    Bull uses Redis as its storage backend, providing durability and reliability for job processing. It supports job retries and delayed jobs, making it ideal for applications that require robust job management.

  • cron:

    Cron does not provide any storage mechanism; it simply executes tasks based on the defined schedule. This is suitable for applications where persistence is not necessary.

  • later:

    Later does not inherently manage job storage; it focuses on defining complex schedules. Users must implement their own storage solution if persistence is required.

  • node-cron:

    Node-Cron is a simple in-memory scheduler that does not provide job persistence. It is best for lightweight applications where tasks do not need to survive application restarts.

  • node-schedule:

    Node-Schedule allows for in-memory scheduling and does not provide built-in persistence. It is suitable for applications where tasks can be redefined upon restart.

Concurrency

  • agenda:

    Agenda processes jobs in a single-threaded manner, which can limit concurrency. However, it allows for job prioritization and can handle multiple jobs if configured properly.

  • bree:

    Bree excels in concurrency by using worker threads, allowing multiple jobs to run simultaneously without blocking the main thread. This is beneficial for CPU-intensive tasks.

  • bull:

    Bull is designed for high concurrency and can handle thousands of jobs simultaneously. It uses Redis to manage job states and supports multiple worker processes for parallel execution.

  • cron:

    Cron runs tasks sequentially based on the defined schedule. It is not designed for concurrent execution, making it suitable for lightweight tasks that do not require parallel processing.

  • later:

    Later allows for scheduling of multiple jobs, but it does not manage concurrency itself. Users need to implement their own concurrency handling if required.

  • node-cron:

    Node-Cron executes tasks sequentially based on the cron schedule. It is not built for concurrent task execution, making it suitable for simple periodic tasks.

  • node-schedule:

    Node-Schedule can handle multiple scheduled tasks, but it does not provide built-in concurrency management. Users must implement their own concurrency logic if needed.

Ease of Use

  • agenda:

    Agenda has a straightforward API that is easy to use for developers familiar with MongoDB. Its integration with MongoDB makes it simple to manage jobs through database operations.

  • bree:

    Bree offers a clean and modern API that is easy to understand. Its focus on simplicity makes it accessible for developers looking for a quick setup without complex configurations.

  • bull:

    Bull has a more complex API due to its extensive features, but it provides comprehensive documentation. Once familiar, developers can leverage its powerful job management capabilities effectively.

  • cron:

    Cron has a simple syntax for defining schedules, making it easy to use for basic task scheduling. However, it may lack advanced features for more complex scheduling needs.

  • later:

    Later provides a flexible syntax for defining schedules, but it may require a learning curve for developers unfamiliar with its API. Its power lies in its ability to handle complex schedules.

  • node-cron:

    Node-Cron is very easy to use, with a simple API for defining cron jobs. It is ideal for developers looking for a lightweight solution without additional complexity.

  • node-schedule:

    Node-Schedule has a user-friendly API that allows for both cron-like and date-based scheduling. It is easy to use for developers needing flexibility in scheduling.

Job Management

  • agenda:

    Agenda provides built-in job management features, including job retries, scheduling, and cancellation. It allows developers to easily manage job states and monitor job progress.

  • bree:

    Bree focuses on simplicity in job management, allowing for easy scheduling and execution of tasks. However, it may lack some advanced job management features found in other libraries.

  • bull:

    Bull offers extensive job management capabilities, including job retries, prioritization, delayed jobs, and event listeners for job completion. It is suitable for applications that require robust job handling.

  • cron:

    Cron does not provide job management features; it simply executes tasks based on the defined schedule. Developers must implement their own management logic if needed.

  • later:

    Later allows for defining complex schedules but does not provide built-in job management features. Users need to handle job execution and state management manually.

  • node-cron:

    Node-Cron does not offer job management features; it executes tasks based on the cron schedule without tracking job states. It is best for simple tasks without management needs.

  • node-schedule:

    Node-Schedule allows for scheduling and cancellation of jobs, providing basic job management capabilities. It is suitable for applications that require flexible scheduling.

Use Cases

  • agenda:

    Agenda is well-suited for applications that require persistent job storage, such as background processing in web applications where jobs need to be retried or tracked over time.

  • bree:

    Bree is ideal for applications that need to run tasks concurrently without blocking, such as processing multiple files or handling real-time data streams.

  • bull:

    Bull is perfect for applications that require a robust job queue system, such as e-commerce platforms that need to process orders, send notifications, and handle background tasks efficiently.

  • cron:

    Cron is best for simple, periodic tasks such as running maintenance scripts or sending scheduled emails without the need for complex job management.

  • later:

    Later is suitable for applications that require complex scheduling scenarios, such as scheduling tasks on specific days or times that are not easily defined with standard intervals.

  • node-cron:

    Node-Cron is ideal for lightweight applications that need to run tasks at specific intervals without additional complexity, such as logging or monitoring tasks.

  • node-schedule:

    Node-Schedule is suitable for applications that require a mix of cron-like and date-based scheduling, such as scheduling events based on user input.

How to Choose: agenda vs bree vs bull vs cron vs later vs node-cron vs node-schedule

  • agenda:

    Choose Agenda if you need a simple and lightweight solution for scheduling jobs in MongoDB. It is ideal for applications that require a job queue with persistent storage and supports recurring jobs easily.

  • bree:

    Select Bree for its modern approach to job scheduling with a focus on simplicity and performance. It uses worker threads for concurrency and is suitable for applications that need to run tasks in parallel without blocking the main thread.

  • bull:

    Opt for Bull if you require a robust job and message queue system with Redis support. It is designed for handling large volumes of jobs and provides features like retries, job prioritization, and delayed jobs, making it suitable for complex applications.

  • cron:

    Use Cron if you need a straightforward way to schedule tasks using cron syntax. It is perfect for simple use cases where you want to run tasks at specific times or intervals without additional overhead.

  • later:

    Choose Later for its expressive syntax and flexibility in defining schedules. It is useful for applications that need to handle complex scheduling scenarios beyond simple intervals, such as specific days of the week or month.

  • node-cron:

    Select Node-Cron for its lightweight and easy-to-use interface for scheduling tasks using cron syntax. It is ideal for simple applications that require periodic execution of tasks without the need for persistent storage.

  • node-schedule:

    Opt for Node-Schedule if you need a flexible scheduling library that allows for both cron-like and date-based scheduling. It is suitable for applications that require a combination of both approaches.

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.
InMemoryNotificationChannelāŒāœ…Notifications 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 (removes from database)
await agenda.cancel({ name: 'my-job' });

// 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