Background Jobs (BullMQ)
The queue module provides Redis-backed background job processing using BullMQ. It is registered as a global module so any other module can inject queues without importing it explicitly.
Registered Queues
| Queue Name | Constant | Purpose |
|---|---|---|
email | EMAIL_QUEUE | Transactional email delivery via Resend |
webhook | WEBHOOK_QUEUE | Webhook event processing |
Configuration
The module is registered via QueueModule.register() in the application root:
import { QueueModule } from "./modules/queue";
@Module({
imports: [
QueueModule.register(),
// ...
],
})
export class AppModule {}
Redis Connection
The module reads the REDIS_URL environment variable and parses it into host, port, password, database, and TLS settings. If REDIS_URL is not set, it falls back to localhost:6379.
Default Job Options
All queues share these defaults:
| Option | Value |
|---|---|
attempts | 3 |
backoff | Exponential, 1 second base delay |
This means a failed job is retried up to 3 times with delays of 1s, 2s, and 4s.
Creating a Job Processor
To process jobs from a queue, create a processor class that extends WorkerHost:
import { Processor, WorkerHost } from "@nestjs/bullmq";
import { Job } from "bullmq";
import { EMAIL_QUEUE } from "../queue/constants";
@Processor(EMAIL_QUEUE)
export class EmailProcessor extends WorkerHost {
async process(job: Job): Promise<void> {
// Handle the job
}
}
Register the processor in the corresponding module's providers array.
Adding a New Queue
- Add a constant to
apps/api/src/modules/queue/constants.ts:
export const MY_QUEUE = "my-queue";
- Register it in
QueueModule.register()by adding to theBullModule.registerQueuecall:
BullModule.registerQueue(
{ name: EMAIL_QUEUE },
{ name: WEBHOOK_QUEUE },
{ name: MY_QUEUE },
),
- Inject the queue in your service:
import { InjectQueue } from '@nestjs/bullmq';
import { Queue } from 'bullmq';
constructor(@InjectQueue('my-queue') private readonly myQueue: Queue) {}
Graceful Fallback
When Redis is not available, BullMQ connection attempts will fail. Services that depend on queues (like EmailService) use @Optional() injection to detect this and fall back to synchronous in-process handling. See the Email module for an example of this pattern.
Environment Variables
REDIS_URL=redis://localhost:6379