agenda
A lightweight, TypeScript-first Node.js job scheduler with pluggable MongoDB, PostgreSQL, and Redis backends.
Repository Health
Technical Analysis
Agenda is a lightweight, TypeScript-first job scheduling library for Node.js, rewritten in v6 around a pluggable backend architecture. Instead of hard-wiring itself to one database, Agenda defines a small AgendaBackend interface — implemented by separate MongoDB, PostgreSQL, and Redis packages — so the same job-definition and scheduling API works across all three, with real-time push notifications available wherever the backend supports pub/sub or LISTEN/NOTIFY instead of pure polling.
Jobs can be defined as plain async functions or as class methods using TypeScript decorators, scheduled via cron syntax or human-readable strings like “tomorrow at noon”, and run with configurable concurrency, locking, and optional sandboxed fork-mode isolation. Built-in draining, persistent job-event logging, and a companion Agendash UI round out the operational tooling for running job queues in production Node.js services.
What You Get
- A single scheduler API that works across MongoDB, PostgreSQL, and Redis backends
- Cron and human-readable scheduling (“5 minutes”, “tomorrow at noon”) via agenda.every()/agenda.schedule()
- TypeScript decorators (@JobsController, @Define, @Every) as an alternative to functional job definitions
- Sandboxed job execution via child_process fork mode
- Persistent job event logging queryable through agenda.getLogs() and viewable in Agendash
Common Use Cases
- Queuing transactional emails and notifications from web request handlers
- Running scheduled report/digest jobs without a separate system cron daemon
- Coordinating job locking and concurrency across multiple running Node.js instances
- Draining in-flight jobs gracefully before container or platform shutdown
Under The Hood
Architecture
The Agenda class (an EventEmitter subclass in src/index.ts) orchestrates job definitions, scheduling, and a JobProcessor (src/JobProcessor.ts) that polls, locks, and runs jobs via a JobProcessingQueue (src/JobProcessingQueue.ts); each job is represented by a Job instance (src/Job.ts) wrapping its stored JobParameters. Storage and notifications are abstracted behind an AgendaBackend interface (src/types/AgendaBackend.ts), composed of a JobRepository (src/types/JobRepository.ts) and an optional NotificationChannel (src/types/NotificationChannel.ts) — separate backend packages (mongo-backend, postgres-backend, redis-backend) implement these, keeping the core package free of any specific database driver. Sandboxed execution is supported via Node’s child_process fork (the forkHelper option consumed in Job.ts), and decorators (src/decorators/Define.ts, Every.ts, JobsController.ts, register.ts) provide a class-based registration path that funnels into the same define()/every() calls used by the plain functional API. What breaks if the AgendaBackend abstraction changes is every backend package and any custom backend implementers — the core Agenda/Job/JobProcessor trio stays fully decoupled from storage specifics.
Tech Stack
The repo is a pnpm workspace monorepo building six packages, of which this is the core. It is TypeScript-only and ESM ("type": "module"), targeting Node.js 18+, compiled via tsc with composite project references and a shared strict tsconfig.base.json (strict mode, NodeNext resolution, noImplicitAny, noImplicitReturns). Runtime dependencies are minimal and focused: cron-parser and human-interval for schedule-string and cron parsing, date.js for natural-language date parsing, luxon for date arithmetic, and debug for namespaced logging — database access itself is deferred entirely to the peer backend packages, which are not dependencies of core agenda. Tests run on Vitest with v8 coverage; releases are managed with Changesets and a dedicated publish.yml GitHub Actions workflow, with API docs built and published via a separate docs.yml workflow.
Code Quality
The package ships an extensive test suite, including several shared cross-backend contract suites (agenda-test-suite.ts, repository-test-suite.ts, jobprocessor-test-suite.ts, notification-channel-test-suite.ts, retry-test-suite.ts, debounce-test-suite.ts, backoff-test-suite.ts, joblogger-test-suite.ts, removeoncomplete-test-suite.ts) that each backend package re-runs against its own implementation to catch backend-specific regressions. ESLint is configured with typescript-eslint recommended rules plus no-console: error and strict unused-vars checking, layered with eslint-config-prettier. CI runs a dedicated test workflow alongside GitHub CodeQL security scanning and a changeset-validation workflow that enforces a changelog entry per pull request. Errors are surfaced through emitted fail/error events rather than silently swallowed in the core control flow.
What Makes It Unique
Agenda’s v6 rewrite differentiates itself from most Node.js job schedulers by making the storage and notification layer fully pluggable behind one AgendaBackend interface, rather than hard-wiring itself to a single database — the same core scheduler logic runs unmodified against MongoDB, PostgreSQL (via LISTEN/NOTIFY), or Redis (via Pub/Sub), letting consumers get push-based job pickup without switching schedulers. It further supports sandboxed job execution via child_process fork isolation and a TypeScript-decorator-based class API as an alternative to plain functional define() calls — a combination of ergonomic flexibility and backend portability not common among comparable schedulers, though an incremental rather than wholly novel architectural choice.