Skip to main content
BullMQ provides two approaches to achieve concurrency: using a local concurrency factor or running multiple worker instances across different processes or machines.

Local Concurrency Factor

The concurrency option determines how many jobs a single worker instance can process simultaneously:

How It Works

When concurrency is set to a value greater than 1, the worker will:
  1. Fetch multiple jobs from the queue (up to the concurrency limit)
  2. Process them concurrently using Node.js’s event loop
  3. Maintain “at-least-once” delivery guarantees
  4. Preserve the order of job fetching (not processing)
Concurrency is most effective for I/O-bound operations like database queries, HTTP requests, or file system operations. Node.js handles these efficiently through its event loop.

Dynamic Concurrency Adjustment

You can adjust the concurrency value while the worker is running:

Use Case: Adaptive Scaling

CPU-Intensive Work: Use Sandboxing

For CPU-intensive operations that block the event loop, use Sandboxed Processors instead of increasing concurrency. High concurrency with blocking operations can lead to stalled jobs.
When to use concurrency vs sandboxing:

Multiple Worker Instances

The recommended approach for production is running multiple worker processes:

Single Machine, Multiple Processes

Multiple Machines

Deploy the same worker code across multiple servers:
Benefits of multiple workers:
  • High availability: If one worker crashes, others continue processing
  • Load distribution: Work is distributed across multiple machines
  • Resource utilization: Each machine’s CPU/memory is used efficiently
  • Scalability: Add more workers as job volume increases

Combining Strategies

For optimal performance, combine multiple workers with concurrency:

Concurrency vs Global Concurrency

Worker concurrency controls how many jobs a single worker processes simultaneously. For limiting jobs across all workers, see Global Concurrency.

Monitoring Concurrency

Track active job count:

Best Practices

1

Start with conservative values

Begin with low concurrency (5-10) and increase based on monitoring.
2

Match workload type

  • I/O-bound: High concurrency (20-100)
  • CPU-bound: Use sandboxing with concurrency = CPU cores
  • Mixed: Medium concurrency (10-20) + sandboxing for heavy tasks
3

Monitor resource usage

Watch CPU, memory, and Redis connection count. Adjust concurrency if limits are hit.
4

Use multiple workers in production

Don’t rely on a single worker process. Distribute across multiple processes/machines.
5

Set appropriate lockDuration

Higher concurrency may need longer locks:

Sandboxed Processors

Isolate CPU-intensive work

Stalled Jobs

Understand and prevent stalled jobs

Global Concurrency

Limit jobs across all workers

Rate Limiting

Control job processing rate

API Reference