DEV Community

Cover image for πŸš€ Handling Cron Jobs in NestJS with Multiple Instances using Bull
Juan Castillo
Juan Castillo

Posted on

2

πŸš€ Handling Cron Jobs in NestJS with Multiple Instances using Bull

Introduction

Cron jobs are essential when you need to execute scheduled tasks in your application. But what happens when you have multiple instances running? 🀯 Without proper handling, each instance might execute the job simultaneously, causing duplicate processing and potential data inconsistencies.

A solid solution is using Bull (a Node.js queue library based on Redis) to ensure that only one instance executes the cron job at a time. In this article, we'll explore how to achieve this using NestJS and Bull.


πŸ›  Setting Up Bull in NestJS

1️⃣ Install Dependencies

First, install Bull and Redis client:

npm install --save @nestjs/bull bull ioredis
Enter fullscreen mode Exit fullscreen mode

2️⃣ Configure BullModule

In your app.module.ts, configure Bull to use Redis:

import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bull';
import { MyCronJobProcessor } from './cron.processor';
import { MyCronJobService } from './cron.service';

@Module({
  imports: [
    BullModule.forRoot({
      redis: {
        host: 'localhost', // Use the Redis host
        port: 6379, // Default Redis port
      },
    }),
    BullModule.registerQueue({
      name: 'cronQueue',
    }),
  ],
  providers: [MyCronJobProcessor, MyCronJobService],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Note: Ensure Redis is running locally or use a cloud-hosted Redis service.


🎯 Implementing the Cron Job

3️⃣ Creating the Cron Job Service

We’ll create a service that adds jobs to the queue at scheduled intervals.

import { Injectable } from '@nestjs/common';
import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bull';
import { Cron } from '@nestjs/schedule';

@Injectable()
export class MyCronJobService {
  constructor(@InjectQueue('cronQueue') private cronQueue: Queue) {}

  @Cron('*/5 * * * * *') // Runs every 5 seconds
  async scheduleJob() {
    await this.cronQueue.add('processData', {});
    console.log('Cron job added to the queue βœ…');
  }
}
Enter fullscreen mode Exit fullscreen mode

The @Cron decorator schedules the job at a fixed interval, ensuring that the task is queued rather than executed by every instance.


4️⃣ Processing the Cron Job

Only one instance should process the job at a time. Bull takes care of that for us! πŸŽ‰

import { Process, Processor } from '@nestjs/bull';
import { Job } from 'bull';

@Processor('cronQueue')
export class MyCronJobProcessor {
  @Process('processData')
  async handleCronJob(job: Job) {
    console.log('Processing cron job... πŸ€–', job.id);
    // Your task logic here (e.g., database cleanup, report generation)
  }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ Create a Docker compose

If you run multiple instances of your NestJS app, only one instance will process the queued job, thanks to Redis locking mechanisms in Bull.

version: '3.8'

services:
  redis:
    image: redis:6.2
    restart: always
    ports:
      - '6379:6379'
    networks:
      - app-network

  worker:
    image: node:18
    working_dir: /app
    volumes:
      - .:/app
    command: ["npm", "run", "start"]
    environment:
      - NODE_ENV=production
      - REDIS_HOST=redis
    networks:
      - app-network
    deploy:
      replicas: 3  # Example: Run 3 instances of the worker
      restart_policy:
        condition: on-failure

networks:
  app-network:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

Run:

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

Now, your Redis instance is ready to use! πŸš€


βœ… Conclusion

Using Bull with Redis in NestJS, we’ve ensured that:

βœ”οΈ Cron jobs are scheduled only once per interval
βœ”οΈ Multiple instances don’t trigger duplicate executions
βœ”οΈ Scalability is achieved with a queue-based approach

Now you’re ready to handle scheduled tasks like a pro! πŸ’ͺπŸ”₯

Happy coding! πŸš€

ACI image

ACI.dev: Best Open-Source Composio Alternative (AI Agent Tooling)

100% open-source tool-use platform (backend, dev portal, integration library, SDK/MCP) that connects your AI agents to 600+ tools with multi-tenant auth, granular permissions, and access through direct function calling or a unified MCP server.

Star our GitHub!

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

Survey image

Shape the Future of Cloud Dev - Win Big!

Share your cloud dev experience in the Developer Nation Survey. Win AI credits, gear & more!

Start Now