Queues and Background Tasks in TypeScript: How Not to Crash Production

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Your Server Sleeps When It Should Be Working

\n\n

Imagine: a user clicks the "Send Report" button, and the page freezes for 30 seconds. The server generates a PDF, compresses images, and sends an email — all synchronously. Sound familiar? If so, you've fallen into the trap of blocking code.

\n\n

In this article, we'll explore how queues and background tasks in TypeScript solve this problem. You'll learn how to offload heavy work to background processes without losing control over errors and scalability. This material is written for developers already familiar with Node.js who want to take their project to the next level.

\n\n

We'll discuss the Bull and BullMQ libraries, touch on RabbitMQ, and show real code examples in TypeScript. Let's go!

\n\n

What Is a Task Queue and Why Do You Need It

\n\n

A task queue is a mechanism that separates a user request from its execution. Instead of processing an operation directly in an HTTP handler, we send a job to a queue, and a background worker picks it up and executes it asynchronously.

\n\n

Typical Use Cases

\n
    \n
  • Sending emails and push notifications
  • \n
  • Generating PDFs, images, videos
  • \n
  • Data parsing and web scraping
  • \n
  • Processing orders in online stores
  • \n
  • Mass calculations and reports
  • \n
\n\n

Without queues, your application risks crashing under load. With them, you gain fault tolerance (if a worker crashes, the job is not lost) and scalability (you can run 10 workers instead of one).

\n\n

Bull and BullMQ: Powerful Queues for Node.js

\n\n

Bull is the most popular library for working with queues in the Node.js ecosystem. It is based on Redis and supports TypeScript out of the box. BullMQ is its successor, more modern, with support for sandboxes (isolated processes) and advanced management.

\n\n

Installation and Basic Setup

\n
npm install bullmq ioredis\nnpm install -D @types/bull
\n\n

Let's create a queue and a worker in TypeScript:

\n\n
// queue.ts\nimport { Queue } from 'bullmq';\n\nconst connection = {\n  host: 'localhost',\n  port: 6379,\n};\n\nexport const emailQueue = new Queue('email', { connection });
\n\n
// worker.ts\nimport { Worker } from 'bullmq';\nimport { sendEmail } from './emailService';\n\nconst worker = new Worker('email', async job => {\n  const { to, subject, body } = job.data;\n  await sendEmail(to, subject, body);\n  console.log(`Email sent to ${to}`);\n}, { connection });\n\nworker.on('completed', job => {\n  console.log(`Job ${job.id} completed`);\n});\n\nworker.on('failed', (job, err) => {\n  console.error(`Job ${job.id} failed: ${err.message}`);\n});
\n\n

Now, anywhere in the application, we can add a task:

\n\n
import { emailQueue } from './queue';\n\nawait emailQueue.add('send-welcome', {\n  to: 'user@example.com',\n  subject: 'Welcome!',\n  body: 'Thank you for registering...'\n});
\n\n

Simple, right? But this is just the beginning. BullMQ offers much more.

\n\n

Advanced BullMQ Features

\n
    \n
  • Retries — if a job fails, it can be automatically restarted after N seconds.
  • \n
  • Delayed execution — postpone a job for a specific time.
  • \n
  • Priorities — urgent jobs are processed first.
  • \n
  • Events — you can subscribe to progress, completion, and errors.
  • \n
  • Sandboxes — executing code in an isolated process (security + cleanliness).
  • \n
\n\n

Example with retries and delay:

\n\n
await emailQueue.add('send-invoice', {\n  invoiceId: 123,\n  email: 'client@example.com'\n}, {\n  attempts: 5,\n  backoff: { type: 'expon                

Blogs

Book Recommendations