Back to all posts

Implementing Background Jobs in NestJS with Bull

S
sonhp
7 min read

Implementing Background Jobs in NestJS with Bull

For applications that require task scheduling, email processing, or data synchronization, background jobs are essential. NestJS integrates seamlessly with Bull, a powerful Redis-based queue system.

In this guide, we'll set up background jobs in NestJS using Bull.

Why Use Bull for Background Jobs?

  • Redis-backed queues ensure high performance and reliability.
  • Job retries and failure handling are built-in.
  • Concurrency control allows efficient processing.

Setting Up Bull in NestJS

1. Install Dependencies

First, install Bull and Redis:

npm install @nestjs/bull bull ioredis

Then, install types for Bull:

npm install --save-dev @types/bull

2. Configure Bull in NestJS

Create a BullModule configuration in app.module.ts:

import { BullModule } from '@nestjs/bull';

@Module({
  imports: [
    BullModule.forRoot({
      redis: {
        host: 'localhost',
        port: 6379,
      },
    }),
  ],
})
export class AppModule {}

This connects Bull to Redis.


3. Creating a Job Queue

Define a queue named "email":

import { BullModule } from '@nestjs/bull';

@Module({
  imports: [
    BullModule.registerQueue({
      name: 'email',
    }),
  ],
})
export class EmailModule {}

4. Implementing a Job Processor

Create a job processor that listens to the "email" queue:

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

@Processor('email')
export class EmailProcessor {
  @Process()
  async handleEmailJob(job: Job) {
    console.log(`Processing email job with data:`, job.data);

    // Simulate email sending
    await sendEmail(job.data);
  }
}

5. Adding Jobs to the Queue

Create a job producer to add jobs dynamically:

import { InjectQueue } from '@nestjs/bull';
import { Queue } from 'bull';

@Injectable()
export class EmailService {
  constructor(@InjectQueue('email') private readonly emailQueue: Queue) {}

  async sendEmail(data: { to: string; subject: string; body: string }) {
    await this.emailQueue.add(data, {
      attempts: 3, // Retry failed jobs up to 3 times
      removeOnComplete: true, // Clean up successful jobs
    });
  }
}

6. Handling Job Failures & Retries

To handle job failures:

@Processor('email')
export class EmailProcessor {
  @Process()
  async handleEmailJob(job: Job) {
    try {
      await sendEmail(job.data);
    } catch (error) {
      console.error(`Job failed:`, error);
      throw error;
    }
  }
}

Bull will automatically retry failed jobs based on the attempts option.


Conclusion

Background jobs in NestJS improve performance and scalability by offloading tasks like email sending, notifications, and data processing. Using Bull with Redis allows efficient queue management, retries, and concurrency handling.

S

Written by sonhp

Technical writer and developer passionate about web technologies.

Related Articles