This episode covers background work in NestJS: task scheduling with @nestjs/schedule, queue processing with Bull and BullMQ, retry policies and delayed jobs, and how to monitor jobs and handle failures.

Not every job can be completed within a single HTTP request. Sending emails, processing images, or syncing data to another service should run in the background. NestJS provides tools for two of these needs: scheduled tasks with @nestjs/schedule and job queues with BullMQ.
npm install @nestjs/schedule@Module({
imports: [ScheduleModule.forRoot()],
})
export class AppModule {}ScheduleModule.forRoot() enables the scheduler across the whole application.
The @Cron decorator runs a method on a specific schedule:
@Injectable()
export class CleanupService {
private readonly logger = new Logger(CleanupService.name);
@Cron("0 3 * * *")
handleCleanup(): void {
this.logger.log("Membersihkan data kedaluwarsa");
}
}The cron expression "0 3 * * *" means run every day at 03:00. This syntax is familiar to anyone who has used cron on an operating system.
For interval-based schedules:
@Injectable()
export class TaskService {
@Interval(60000)
everyMinute(): void {
console.log("Berjalan setiap 60 detik");
}
@Timeout(5000)
afterStartup(): void {
console.log("Berjalan 5 detik setelah start");
}
}@Interval repeats continuously, @Timeout runs only once after the application starts.
BullMQ is a popular Redis-based queue library for NestJS:
npm install @nestjs/bullmq bullmqBullMQ requires a running Redis — start one via Docker with docker run --name redis -p 6379:6379 -d redis:7.
@Module({
imports: [
BullModule.forRoot({
connection: { host: "localhost", port: 6379 },
}),
BullModule.registerQueue({
name: "email",
}),
],
})
export class EmailModule {}BullModule.registerQueue registers the email queue that will be used to send jobs.
A producer adds jobs to the queue:
@Injectable()
export class EmailProducer {
constructor(@InjectQueue("email") private readonly emailQueue: Queue) {}
async sendWelcomeEmail(userId: number): Promise<void> {
await this.emailQueue.add("welcome", { userId });
}
}A consumer processes jobs:
@Processor("email")
export class EmailConsumer extends WorkerHost {
async process(job: Job): Promise<void> {
if (job.name === "welcome") {
console.log(`Mengirim email ke user ${job.data.userId}`);
}
}
}@Processor("email") marks the class as a worker that processes jobs from the email queue.
BullMQ supports per-job retry and delay configuration:
await this.emailQueue.add("welcome", { userId }, {
attempts: 3,
backoff: { type: "exponential", delay: 2000 },
delay: 60000,
});attempts: 3 retries the job up to three times, backoff increases the wait between attempts, and delay postpones the first execution by 60 seconds.
A worker can process several jobs at once with the concurrency option on @Processor, and failures can be monitored through the @OnWorkerEvent hook:
@Processor("email", { concurrency: 5 })
export class EmailConsumer extends WorkerHost {
@OnWorkerEvent("completed")
onCompleted(job: Job): void {
console.log(`Job ${job.id} selesai`);
}
@OnWorkerEvent("failed")
onFailed(job: Job, err: Error): void {
console.error(`Job ${job.id} gagal: ${err.message}`);
}
}concurrency: 5 makes the worker process five jobs in parallel, while the completed and failed hooks signal the outcome. Jobs that fail after all attempts can be moved to a dedicated queue (dead letter) or recorded for manual inspection. For a visual dashboard, tools like Bull Board display pending, active, and failed jobs.
Episode 11 equips you with background work: scheduling with cron, intervals, and timeouts; queue processing with BullMQ; retry and delayed jobs; plus monitoring and failure handling.
Key takeaways:
@nestjs/schedule handles scheduled tasks with cron, intervals, and timeouts.attempts and backoff configure automatic retries.delay postpones job execution, concurrency controls parallelism.In the next episode 12 we'll discuss security and authentication — NestJS security fundamentals, JWT authentication and guards, Passport integration with auth strategies, and role-based access control and permissions.