← Back to articles

BullMQ vs Quirrel vs pgBoss (2026)

Background jobs handle email sending, image processing, webhooks, and scheduled tasks. Here's how the three main Node.js job queue libraries compare.

Quick Comparison

FeatureBullMQQuirrelpgBoss
BackendRedisHosted/self-hostedPostgreSQL
LanguageTypeScriptTypeScriptTypeScript
Scheduling✅ Cron, delayed✅ Cron, delayed✅ Cron, delayed
Retries✅ Configurable✅ Configurable✅ Configurable
Priority
Rate Limiting
DashboardBull BoardBuilt-in
Extra InfraRedis requiredOptional (hosted)Uses your Postgres
Best ForHigh-throughputServerless/Next.jsPostgres-only stacks

BullMQ — The Industry Standard

Best for: High-throughput applications that already use Redis.

import { Queue, Worker } from 'bullmq'

const connection = { host: 'localhost', port: 6379 }

// Create a queue
const emailQueue = new Queue('emails', { connection })

// Add a job
await emailQueue.add('welcome', {
  to: 'user@example.com',
  subject: 'Welcome!',
})

// Add a delayed job (send in 1 hour)
await emailQueue.add('reminder', { to: 'user@example.com' }, {
  delay: 60 * 60 * 1000,
})

// Add a recurring job (every day at 9am)
await emailQueue.add('daily-digest', {}, {
  repeat: { pattern: '0 9 * * *' },
})

// Process jobs
const worker = new Worker('emails', async (job) => {
  await sendEmail(job.data)
}, { connection, concurrency: 5 })

worker.on('completed', (job) => console.log(`Done: ${job.id}`))
worker.on('failed', (job, err) => console.error(`Failed: ${err.message}`))

Pros:

  • Most battle-tested (millions of jobs/day in production)
  • Rate limiting, priority queues, job dependencies
  • Bull Board dashboard for monitoring
  • Excellent TypeScript support
  • Large community and ecosystem

Cons:

  • Requires Redis (extra infrastructure)
  • More complex setup than alternatives
  • Redis costs on cloud providers

Quirrel — The Serverless Queue

Best for: Next.js and serverless apps that don't want to manage Redis.

// app/api/queues/email/route.ts
import { Queue } from 'quirrel/next'

export const emailQueue = Queue('api/queues/email', async (job) => {
  await sendEmail(job.to, job.subject, job.body)
})

// Enqueue from anywhere
await emailQueue.enqueue(
  { to: 'user@example.com', subject: 'Welcome!' },
  { delay: '1h' }
)

// Recurring jobs
await emailQueue.enqueue(
  { type: 'daily-digest' },
  { repeat: { cron: '0 9 * * *' } }
)

Pros:

  • Zero infrastructure (hosted version)
  • Built for serverless (Next.js, Vercel)
  • Simple API
  • Built-in dashboard

Cons:

  • Smaller community
  • Less feature-rich than BullMQ
  • Hosted service dependency (or self-host)
  • No priority queues or rate limiting

pgBoss — The PostgreSQL Queue

Best for: Apps already using PostgreSQL that don't want to add Redis.

import PgBoss from 'pg-boss'

const boss = new PgBoss(process.env.DATABASE_URL)
await boss.start()

// Add a job
await boss.send('emails', {
  to: 'user@example.com',
  subject: 'Welcome!',
})

// Add a scheduled job
await boss.schedule('daily-report', '0 9 * * *')

// Process jobs
await boss.work('emails', { teamConcurrency: 5 }, async (job) => {
  await sendEmail(job.data)
})

Pros:

  • No extra infrastructure (uses your existing Postgres)
  • ACID-compliant (transactional job creation)
  • Simple setup
  • Job archival and monitoring built-in

Cons:

  • Slower than Redis-backed queues at high volume
  • Less battle-tested at massive scale
  • Adds load to your database
  • Fewer features than BullMQ

Also Consider: Inngest & Trigger.dev

These managed platforms handle background jobs without self-managed queues:

Inngest: Event-driven functions with built-in retries, scheduling, and step functions. No queue infrastructure needed.

Trigger.dev: Similar to Inngest but with a focus on long-running tasks and integrations.

Both are excellent if you don't want to manage queue infrastructure at all.

Decision Framework

Already have Redis → BullMQ
Serverless / Next.js → Quirrel or Inngest
PostgreSQL only (no Redis) → pgBoss
Don't want to manage queues → Inngest or Trigger.dev
High throughput (>10K jobs/min) → BullMQ

FAQ

Do I need a job queue?

If you're sending emails, processing images, syncing data, or running scheduled tasks — yes. Don't do these in your API request handler.

Can PostgreSQL handle job queues?

Yes, for moderate volume (thousands of jobs/hour). For high throughput (millions/day), Redis-backed BullMQ is more appropriate.

BullMQ vs Inngest?

BullMQ is self-managed (you run Redis and workers). Inngest is managed (they handle the infrastructure). BullMQ for control, Inngest for simplicity.

Bottom Line

BullMQ is the default for Node.js job queues — battle-tested and feature-rich. pgBoss if you want to avoid Redis. Quirrel for serverless. Inngest/Trigger.dev if you don't want to manage queue infrastructure. Start with what matches your existing infrastructure.

Get AI tool guides in your inbox

Weekly deep-dives on the best AI coding tools, automation platforms, and productivity software.