Bull queue helps your NestJS app handle tasks in the background. It makes your app faster by doing heavy work later.
Bull queue integration in NestJS
import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('queueName') export class QueueProcessor { @Process('jobName') async handleJob(job: Job<any>) { // job.data contains the data sent to the queue // Your job logic here } }
@Processor('queueName') marks the class to handle jobs from a named queue.
@Process('jobName') marks the method to handle a specific job type.
import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('email') export class EmailProcessor { @Process('sendEmail') async sendEmailJob(job: Job<{ email: string }>) { console.log(`Sending email to ${job.data.email}`); } }
import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('image') export class ImageProcessor { @Process('resize') async resizeImage(job: Job<{ imagePath: string }>) { if (!job.data.imagePath) { throw new Error('No image path provided'); } console.log(`Resizing image at ${job.data.imagePath}`); } }
import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('emptyQueue') export class EmptyProcessor { @Process('emptyJob') async handleEmpty(job: Job) { console.log('Job received but no data'); } }
This complete NestJS app sets up Bull with Redis, creates an email queue, and processes a sendEmail job. It adds a job with an email address and prints a message when processing.
import { Module } from '@nestjs/common'; import { BullModule } from '@nestjs/bull'; import { Processor, Process } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('email') export class EmailProcessor { @Process('sendEmail') async sendEmailJob(job: Job<{ email: string }>) { console.log(`Sending email to ${job.data.email}`); } } @Module({ imports: [ BullModule.forRoot({ redis: { host: 'localhost', port: 6379 } }), BullModule.registerQueue({ name: 'email' }) ], providers: [EmailProcessor] }) export class AppModule {} // Simulate adding a job to the queue import { NestFactory } from '@nestjs/core'; import { Queue } from 'bull'; import { InjectQueue } from '@nestjs/bull'; async function bootstrap() { const app = await NestFactory.createApplicationContext(AppModule); const emailQueue = app.get<Queue>('BullQueue_email'); await emailQueue.add('sendEmail', { email: 'user@example.com' }); // Wait a moment to let the processor print setTimeout(() => app.close(), 1000); } bootstrap();
Time complexity: Adding and processing jobs is usually fast, O(1) for queue operations.
Space complexity: Depends on the number and size of jobs stored in Redis.
Common mistake: Forgetting to register the queue in the module or missing Redis connection causes errors.
Use Bull queues when you want to do work outside the main request flow, like sending emails or processing files.
Bull queues let NestJS apps handle tasks in the background.
Use @Processor and @Process decorators to define job handlers.
Register queues and connect to Redis in your module to use Bull.
Practice
Solution
Step 1: Understand Bull queue role
Bull queues are used to process jobs asynchronously, meaning tasks run in the background without blocking the main app.Step 2: Compare options with Bull's purpose
Database migrations, creating REST API endpoints, and styling frontend components relate to other app parts, not background task handling.Final Answer:
To handle tasks asynchronously in the background -> Option CQuick Check:
Bull queues = background task handling [OK]
- Confusing Bull queues with API routing
- Thinking Bull manages database schema
- Assuming Bull is for frontend styling
Solution
Step 1: Recall Bull job handler decorators
In NestJS Bull integration, @Process decorates methods that handle jobs from a queue.Step 2: Verify other options
@QueueHandler, @JobListener, and @QueueJob are not valid NestJS Bull decorators.Final Answer:
@Process -> Option DQuick Check:
Job handler method uses @Process [OK]
- Using non-existent decorators like @QueueHandler
- Confusing @Processor with @Process (class vs method)
- Missing the @Process decorator on job methods
@Processor('email')
export class EmailProcessor {
@Process('send')
async handleSend(job: Job) {
console.log(`Processing job: ${job.data.name}`);
return 'done';
}
}Solution
Step 1: Understand job data access
The job object passed to handleSend contains a data property with { name: 'task1' }.Step 2: Analyze console.log output
The template string uses job.data.name, which is 'task1', so it logs "Processing job: task1".Final Answer:
Processing job: task1 -> Option AQuick Check:
job.data.name = 'task1' logs correctly [OK]
- Assuming job.data is undefined
- Forgetting to await async method
- Thinking method won't be called without explicit call
@Module({
imports: [
BullModule.registerQueue({
name: 'notifications',
redis: {
host: 'localhost',
port: '6379'
}
})
]
})
export class NotificationModule {}Solution
Step 1: Check Redis config types
Redis port must be a number, but here it is given as string '6379'.Step 2: Validate other parts
Queue name as string is valid; 'localhost' is acceptable; BullModule.registerQueue is correct method.Final Answer:
The port value should be a number, not a string -> Option AQuick Check:
Redis port must be number [OK]
- Passing port as string instead of number
- Thinking queue name must be array
- Assuming 'localhost' is invalid host
- Confusing BullModule.registerQueue with other methods
Solution
Step 1: Understand @Processor and @Process usage
A single @Processor class can handle multiple job types from the same queue by defining multiple @Process methods with different job names.Step 2: Evaluate options
Use one @Processor('messages') class with two methods decorated by @Process('email') and @Process('sms') correctly uses one processor class with two @Process methods for 'email' and 'sms'. Create two separate @Processor classes, one for 'email' and one for 'sms', each with a single @Process method splits into classes unnecessarily. Use one @Processor class with a single @Process('email') method handling both job types by checking job.name cannot handle 'sms' jobs since only 'email' jobs trigger the method. Register two queues with the same name and use one @Process method registers duplicate queues which is invalid.Final Answer:
Use one @Processor('messages') class with two methods decorated by @Process('email') and @Process('sms') -> Option BQuick Check:
Multiple @Process methods in one @Processor class [OK]
- Creating multiple processor classes unnecessarily
- Using a single named @Process method for multiple job types
- Registering duplicate queues with same name
Ready to prove it?
Pass the test and this pattern moves unknown
