agenda、bee-queue、bull、bullmq、kue、node-resque はすべて Node.js で非同期ジョブやバックグラウンドタスクを管理するためのライブラリです。これらはジョブをキューに登録し、ワーカープロセスが非同期で処理することで、メール送信、ファイル変換、データ同期などの重い処理をメインアプリケーションから切り離すことを可能にします。各ライブラリはデータストア(MongoDB または Redis)や API 設計、再試行・遅延実行のサポート、保守状況において大きく異なり、アーキテクチャ選定の際に重要な判断材料となります。
Node.js アプリケーションで非同期処理やバックグラウンドジョブを扱う際、信頼性の高いジョブキュー管理ライブラリは不可欠です。本稿では、agenda、bee-queue、bull、bullmq、kue、node-resque の6つの主要なnpmパッケージを、実際の開発現場での使用観点から技術的に比較します。各ライブラリの設計思想、Redis依存の有無、APIスタイル、再試行・遅延実行のサポート、そして保守状況に焦点を当て、プロフェッショナルなフロントエンド開発者がアーキテクチャ選定を行う際に役立つ情報を提供します。
これらのライブラリはすべて「ジョブ(タスク)をキューに登録し、ワーカーが非同期で処理する」という基本的なパターンを実現しますが、裏側で使用するデータストアが大きく異なります。この点がアーキテクチャ選定の最も重要な分岐点です。
agendaagenda は MongoDB 専用のジョブスケジューラです。MongoDB が既にシステムに導入済みで、追加のインフラ(Redisなど)を避けたい場合に最適です。
// agenda: MongoDB にジョブを保存
const Agenda = require('agenda');
const agenda = new Agenda({ db: { address: 'mongodb://localhost:27017/agenda' } });
agenda.define('send email', async (job) => {
await sendEmail(job.attrs.data.to, job.attrs.data.subject);
});
await agenda.start();
agenda.now('send email', { to: 'user@example.com', subject: 'Hello' });
bee-queue、bull、bullmq、kue、node-resque はすべて Redis をデータストアとして使用します。Redis はメモリ上にデータを保持し、高速なキュー処理が可能ですが、永続化設定やクラスタリングなどの運用負荷が伴います。
// bee-queue: Redis を使用
const Queue = require('bee-queue');
const queue = new Queue('email', { redis: { host: 'localhost', port: 6379 } });
queue.process(async (job) => {
return await sendEmail(job.data.to, job.data.subject);
});
queue.createJob({ to: 'user@example.com', subject: 'Hello' }).save();
💡 重要なポイント: MongoDB と Redis のどちらを使うかは、既存のインフラ、チームの運用経験、ジョブの重要度(失敗許容度)によって決まります。
agenda以外は Redis 必須です。
公式情報に基づき、以下のライブラリは 新規プロジェクトでの使用を避けるべきです。
kue: GitHub リポジトリおよび npm ページに明確な非推奨(deprecated)の記載があります。最後の更新は2018年であり、メンテナンスされていません。node-resque: 公式 npm ページに「This package is deprecated. Please use @resque/resque instead.」と記載されています。ただし、@resque/resque は別パッケージのため、ここでは node-resque は非推奨と判断します。✅ 結論: 新規プロジェクトでは
kueとnode-resqueは使用しないでください。代わりにbull、bullmq、bee-queue、agendaを検討しましょう。
ジョブが失敗したときの再試行や、特定時間後に実行する遅延ジョブは、多くのアプリケーションで必要です。各ライブラリの実装方法を比較します。
agenda: スケジューリング機能内蔵agenda は MongoDB の日付クエリを使って、自然な形で遅延と再試行を実現します。
// agenda: 失敗時に最大3回再試行、10分後に再実行
agenda.define('process payment', { retry: 3, retryDelay: 10 * 60 * 1000 }, async (job) => {
// ...
});
// 5分後に実行
agenda.schedule('in 5 minutes', 'process payment', { orderId: 123 });
bee-queue: シンプルで軽量bee-queue は再試行回数を指定できますが、遅延実行は直接サポートしていません(代替手段が必要)。
// bee-queue: 最大2回再試行
const queue = new Queue('task', { activateDelayedJobs: true });
queue.process({ concurrency: 5, retryLimit: 2 }, async (job) => {
// ...
});
// 遅延実行は非サポート(workaround 必要)
bull / bullmq: 機能豊富で柔軟bull と bullmq は再試行、遅延、優先度、レート制限など、ほぼすべての高度な機能をサポートしています。
// bull: 再試行と遅延
const Queue = require('bull');
const queue = new Queue('video transcoding');
queue.process(async (job) => {
// ...
});
// 遅延付きジョブ(5秒後)
queue.add({ videoId: 123 }, { delay: 5000 });
// 再試行設定(指数バックオフ)
queue.add({ videoId: 123 }, {
attempts: 3,
backoff: { type: 'exponential', delay: 1000 }
});
// bullmq: 同様の機能(APIがよりモダン)
import { Queue, Worker } from 'bullmq';
const queue = new Queue('audio');
const worker = new Worker('audio', async (job) => { /* ... */ });
await queue.add('transcode', { file: 'song.mp3' }, {
delay: 5000,
attempts: 3,
backoff: { type: 'exponential', delay: 1000 }
});
💡 ポイント: 複雑なスケジューリングや再試行戦略が必要なら、
bullまたはbullmqが最適です。bee-queueはシンプルさを重視するケース向けです。
bull vs bullmq: 古典的 vs モダンbull はコールバックとPromiseを混在させた古典的なAPIですが、bullmq は完全にPromise/async-await対応で、TypeScriptサポートも優れています。
// bull: クラシックなAPI
const queue = new Bull('tasks');
queue.process((job, done) => {
// 処理後に done() を呼ぶ
done(null, result);
});
// bullmq: モダンなasync/await
const worker = new Worker('tasks', async (job) => {
return await process(job.data);
});
✅ 推奨: 新規プロジェクトでは
bullmqを選ぶのが安全です。bullはまだ使われていますが、bullmqが公式に推奨される次世代版です。
bee-queue: 最小限のAPIbee-queue は「キュー作成 → ジョブ登録 → 処理」の流れが非常にシンプルで、学習コストが低いです。
const queue = new Queue('simple');
queue.process(async (job) => { /* ... */ });
queue.createJob(data).save();
運用中にジョブの状態を確認できるUIがあると便利です。
bull / bullmq: 公式の bull-board というUIツールがあり、簡単に統合できます。agenda: サードパーティ製の agenda-ui がありますが、公式サポートではありません。bee-queue: 公式UIなし。監視にはカスタムスクリプトが必要です。| ライブラリ | データストア | 非推奨 | 特徴 |
|---|---|---|---|
agenda | MongoDB | ❌ | MongoDBユーザー向け、スケジューリング内蔵 |
bee-queue | Redis | ❌ | 軽量・シンプル、高度機能少なめ |
bull | Redis | ❌ | 機能豊富、UIあり、古めのAPI |
bullmq | Redis | ❌ | bull の次世代版、モダンAPI、TypeScript対応 |
kue | Redis | ✅ | 非推奨、新規プロジェクトで使用禁止 |
node-resque | Redis | ✅ | 非推奨、@resque/resque へ移行推奨 |
agenda を選ぶ。bee-queue を選ぶ。bullmq を選ぶ(bull はレガシー案件向け)。kue や node-resque は絶対に新規で使わない — 公式で非推奨と明記されています。これらのライブラリはどれも「ジョブをキューに入れて処理する」という同じゴールを持ちますが、裏側の設計思想と機能セットは大きく異なります。あなたのプロジェクトのインフラ、チームのスキル、将来の拡張性を考慮して、慎重に選んでください。
Redis を使い、最新の async/await 対応、TypeScript サポート、高度なジョブ管理機能(指数バックオフ、レート制限、UI統合)を求める新規プロジェクトに最適です。bull の公式後継として積極的に開発されています。
非推奨のライブラリです。npm ページに「This package is deprecated. Please use @resque/resque instead.」と記載されています。新規プロジェクトでは使用せず、代替パッケージを検討する必要があります。
MongoDB を既に使用しており、追加のインフラ(Redisなど)を避けたい場合に最適です。スケジューリング機能が内蔵されており、日時指定のジョブ実行が自然に実装できます。ただし、Redis を使いたい場合は選択肢から外れます。
軽量でシンプルなAPIを求める場合に適しています。Redis を使用しますが、高度な機能(遅延実行、複雑な再試行戦略)はサポートしておらず、最小限の依存でジョブキューを実現したいプロジェクトに向いています。
Redis を使い、UIダッシュボードや豊富な機能(再試行、遅延、優先度)が必要なレガシーまたは既存プロジェクト向けです。ただし、APIが古く、新規プロジェクトでは bullmq の方が推奨されます。
非推奨のライブラリです。GitHub および npm で明確に deprecated と記載されており、最後の更新は2018年です。新規プロジェクトでは絶対に使用せず、代わりに bullmq や bee-queue を検討してください。
The fastest, most reliable, Redis-based distributed queue for Node.
Carefully written for rock solid stability and atomicity.
Follow Us for *important* Bull/BullMQ/BullMQ-Pro news and updates!
You can find tutorials and news in this blog: https://blog.taskforce.sh/
Do you need to work with BullMQ on platforms other than Node.js? If so, check out the BullMQ Proxy
Supercharge your queues with a professional front end:
Sign up at Taskforce.sh
|
| 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. |
Some notable organizations using BullMQ:
|
|
|
|
|
|
|
|
|
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
Since there are a few job queue solutions, here is a table comparing them:
| Feature | BullMQ-Pro | BullMQ | Bull | Kue | Bee | Agenda |
|---|---|---|---|---|---|---|
| Backend | redis | redis | redis | redis | redis | mongo |
| 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 for | Jobs / Messages | Jobs / Messages | Jobs / Messages | Jobs | Messages | Jobs |
Fork the repo, make some changes, submit a pull-request! Here is the contributing doc that has more details.
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.