In modern web applications, certain tasks must run asynchronously in the background without interrupting the main request response cycle like generating reports, handling payments, sending emails,and more. This is where background job processing is useful.
BullMQ is a powerful, high-performance job queue built on Redis that enables scalable job processing in Node.js applications. Let’s explore how to set up and use BullMQ with Redis to handle background jobs efficiently.
BullMQ offers several advantages for background job processing:
Before we start, ensure you have the following:
Node.js Installed (LTS recommended)
Redis Installed and Running # Start Redis locally (if installed)
redis-server
Install Required Dependencies -
npm install bullmq ioredis express
1. Creating a Job Queue
To start using BullMQ, create a queue to add jobs:
import { Queue } from "bullmq";
const emailQueue = new Queue("newEmailQueue", {
connection: {
host: "127.0.0.1", port: 6379 },
});
async function newEmailJob( email: string ) {
await emailQueue.add("sendMail", { email });
console.log(`Job added to queue: ${email}`);
}
newEmailJob("jon.doe@example.com");
2. Creating a Worker to Process Jobs
A worker listens for jobs and processes them when available.
import { Worker } from "bullmq";
const emailWorker = new Worker( "emailQueue", async (job) => {
console.log(`Started processing for the job: ${job.data.email}`);
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log(`Email sent!!`);
},
{ connection: { host: "127.0.0.1", port: 6379 } }
);
console.log("Successfully started worker!");
Jobs may sometimes fail due to temporary issues (e.g., network failures). BullMQ supports automatic retries.
const emailWorker = new Worker("emailQueue",
async (job) => {
if (Math.random() < 0.5) {
throw new Error("Random failure"); // Simulate a failure
}
console.log(`Started processing job => ${job.data.email}`);
},
{
connection: { host: "127.0.0.1", port: 6379 },
attempts: 5, // Retry up to 5 times
}
);
emailWorker.on("failed", (job, err) => {
console.error(`Job failed for ${job.data.email}: ${err.message}`);
});
Adding Delayed Jobs
Delay a job execution for a certain period:
await emailQueue.add("sendEmail",
{ email: "jon.doe@example.com" },
{ delay: 4000 } // Delay execution by 4 seconds
);
Schedule jobs using cron expressions.
import { QueueScheduler } from "bullmq";
new QueueScheduler("emailQueue", { connection:
{ host: "127.0.0.1", port: 6379
} });
await emailQueue.add("sendDailyEmail",
{ email: "admin@example.com" },
{ repeat: { cron: "0 7 * * *" } } // Run every day at 7 AM
);
npm install @bull-board/express
import { ExpressAdapter } from "@bull-board/express";
import { createBullBoard } from "@bull-board/api";
import express from "express";
const serverAdapter = new ExpressAdapter();
createBullBoard({queues: [new BullMQAdapter(emailQueue)], serverAdapter });
const app = express();
serverAdapter.setBasePath("/admin/queues");
app.use("/admin/queues", serverAdapter.getRouter());
app.listen(4000, () => console.log("Dashboard running on http://localhost:4000/admin/queues"));
Use Separate Redis Instances for different environments (e.g., dev, staging, production).
Monitor Job Failures and implement retry strategies.
Use Job Prioritization to handle urgent tasks first.
Limit Worker Concurrency to avoid Redis overload: new Worker("emailQueue", async () => {}, { concurrency: 5 });
Persist Jobs in the Database if needed for audit logs.
Ready to transform your business with our technology solutions? Contact Us today to Leverage Our NodeJS Expertise.