Queues Basics
8 examples to get you started with queues and workers for Node.js - 6 basic and 2 intermediate.
Search across all documentation pages
8 examples to get you started with queues and workers for Node.js - 6 basic and 2 intermediate.
npm install bullmq ioredis
npm install -D typescript@5.6 tsxRedis 7 required for BullMQ. See BullMQ for production worker setup.
| In HTTP request | In worker |
|---|---|
| Send email | OK |
| Resize 50 images | Queue |
| Charge card + fulfill | Queue after idempotency key |
| Return search results <100ms | Sync DB only |
Related: BullMQ - Redis-backed queues
import { Queue } from "bullmq";
import IORedis from "ioredis";
const connection = new IORedis(process.env.REDIS_URL!, { maxRetriesPerRequest: null });
const emailQueue = new Queue("email", { connection });
app.post("/invite", async (req, res) => {
const job = await emailQueue.add("send-invite", {
to: req.body.email,
orgId: req.body.orgId,
});
res.status(202).json({ jobId: job.id });
});202 Accepted signals async processingimport { Worker } from "bullmq";
import IORedis from "ioredis";
const connection = new IORedis(process.env.REDIS_URL!, { maxRetriesPerRequest: null });
new Worker(
"email",
async (job) => {
if (job.name === "send-invite") {
await sendInviteEmail(job.data.to, job.data.orgId);
}
},
{ connection, concurrency: 5 }
);concurrency bounds parallel jobs per worker podawait emailQueue.add(
"send-invite",
{ to, orgId },
{
attempts: 5,
backoff: { type: "exponential", delay: 2000 },
removeOnComplete: 1000,
removeOnFail: false,
}
);removeOnFail: false)attempts so poison messages eventually stopRelated: Retries with Backoff
app.get("/jobs/:id", async (req, res) => {
const job = await emailQueue.getJob(req.params.id);
if (!job) return res.status(404).json({ error: "not_found" });
const state = await job.getState();
res.json({ id: job.id, state, progress: job.progress });
});waiting, active, completed, failed, delayedawait paymentsQueue.add("capture", { paymentId, idempotencyKey }, { jobId: idempotencyKey });jobId dedupes duplicate enqueue from client retriesapi/ -> HTTP + enqueue only
worker-email/ -> BullMQ Worker
worker-media/ -> heavy CPU queue
Related: Reference Worker Fleet
| Trigger | Tool |
|---|---|
| User action | Queue job now |
| Every night 2am | Cron + optional leader lock |
| Every 5 minutes | BullMQ repeatable job |
BullMQ requires Redis. AWS SQS is alternative - see AWS SQS Consumers.
Sub-50ms p95. Enqueue is one Redis round trip.
Jobs accumulate in queue. Alert on depth; scale workers or fix consumer.
No. Aim at-least-once with idempotent workers.
@nestjs/bullmq wraps BullMQ modules. Same retry and idempotency rules.
BullMQ supports priority numbers. Use sparingly - starves low priority if abused.
delay: 60000 for scheduled send. Repeatable for cron patterns.
Store blob in S3; queue only reference id. Redis job payload stays small.
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.
Reviewed by Chris St. John·Last updated Jul 16, 2026