·QueueHub Team·11 min read

QueueHub vs pg-boss: Redis vs PostgreSQL as a Job Queue Backend

BullMQpg-bossQueueHubPostgreSQL queueRedis queueNode.js job queuetransactional queue

pg-boss is a Node.js job queue that uses PostgreSQL as its backend. BullMQ is a Node.js job queue that uses Redis. Both are mature, both are OSS, and both are widely deployed. QueueHub is a dashboard that monitors BullMQ (and BeeQueue and SQS).

The interesting comparison here isn't really QueueHub vs pg-boss — it's Redis-backed queues vs PostgreSQL-backed queues. Once you pick a backend, the dashboard question follows naturally, but the backend choice has architectural consequences that are worth understanding.

This post compares the two approaches across throughput, persistence, transactional enqueueing, deployment, and operational fit.

TL;DR Comparison

Dimension pg-boss (PostgreSQL) BullMQ + QueueHub (Redis)
Backend PostgreSQL Redis
Throughput Moderate (hundreds–low thousands/sec) High (thousands–tens of thousands/sec)
Persistence ACID, durable by default Configurable (RDB / AOF)
Transactional enqueue ✓ (same transaction as DB write) — (separate system)
Job priorities ✓ (native)
Scheduling ✓ (repeatable jobs)
Batches / flows ✓ (fetch patterns) ✓ (BullMQ flows)
Dashboard None bundled QueueHub (hosted SaaS)
Multi-backend dashboard pg-boss only BullMQ + BeeQueue + SQS

What Is pg-boss?

pg-boss is a Node.js job queue library that stores jobs in PostgreSQL. Instead of running Redis alongside Postgres, you use Postgres for both your application data and your job queue.

A pg-boss setup:

import PgBoss from 'pg-boss';

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

const queue = await boss.createQueue('email');

// Enqueue
await queue.send({ name: 'welcome', data: { userId: 42 } });

// Worker
await boss.work('email', async (jobs) => {
  for (const job of jobs) {
    const { userId } = job.data;
    await Mailer.send(await User.findById(userId), 'welcome');
  }
});

pg-boss's Strengths

  • Uses PostgreSQL. If you already run Postgres, pg-boss adds no new infrastructure. One database to back up, monitor, and operate.
  • Transactional enqueueing. You can enqueue a job in the same SQL transaction as a data write. If the transaction commits, the job exists; if it rolls back, the job doesn't. This is a powerful pattern.
  • ACID durability. PostgreSQL's durability guarantees apply to your jobs. Once committed, a job survives database crashes.
  • Schema-based isolation. Multiple pg-boss instances can use different Postgres schemas.
  • No separate Redis dependency. One fewer moving part.

pg-boss's Limitations

  • Lower throughput. PostgreSQL is a general-purpose OLTP database, not a specialized in-memory data store. Job throughput is lower than Redis-backed queues — typically hundreds to low thousands of jobs per second, depending on hardware and Postgres tuning.
  • No bundled dashboard. pg-boss has no web UI. You inspect jobs via SQL queries (SELECT * FROM pgboss.job) or build your own admin tooling.
  • Lock contention at scale. At high concurrency, Postgres row locks on the job table can become a bottleneck.
  • No multi-backend. pg-boss only monitors pg-boss queues. If you also run BullMQ or SQS, you need separate tools.

What Is BullMQ + QueueHub?

BullMQ is a TypeScript-native job queue for Node.js using Redis. QueueHub is a hosted dashboard for monitoring BullMQ, BeeQueue, and Amazon SQS.

A BullMQ setup:

import { Worker, Queue } from 'bullmq';
import IORedis from 'ioredis';

const connection = new IORedis(process.env.REDIS_URL);

const emailQueue = new Queue('email', { connection });

const worker = new Worker(
  'email',
  async (job) => {
    const { userId, template } = job.data;
    const user = await User.findById(userId);
    await Mailer.send(user, template);
  },
  { connection, concurrency: 10 }
);

// Enqueue
await emailQueue.add('welcome', { userId: 42 });

BullMQ's Strengths

  • High throughput. Redis is in-memory and optimized for high-frequency operations. BullMQ can handle thousands to tens of thousands of jobs per second per worker.
  • Rich OSS feature set. Priorities, delays, repeatable jobs, flows (parent/child), rate limiting, concurrency control — all free.
  • TypeScript-native with full type safety.
  • Excellent Redis efficiency using Streams and event notifications.
  • Mature monitoring options. Bull Board, Arena, Taskforce, and QueueHub all support BullMQ.

BullMQ's Limitations

  • Requires Redis. If you don't already run Redis, this is a new piece of infrastructure.
  • No transactional enqueueing. Enqueuing a BullMQ job and committing a database row are separate operations. If the DB commit succeeds but the enqueue fails (or vice versa), you have an inconsistency.
  • Durability is Redis-specific. Redis persistence (RDB / AOF) is configurable but not ACID. If Redis crashes between a write and an RDB snapshot, the job can be lost.

The Core Trade-Off: Throughput vs Transactional Semantics

This is the heart of the comparison, and it's worth being precise about.

Redis (BullMQ): Optimized for throughput

Redis is an in-memory data store. Operations are fast (sub-millisecond on a local network), and BullMQ uses Redis Streams and Lists to achieve high throughput. For workloads like:

  • High-volume email sending,
  • Real-time image processing,
  • Webhook fanout,
  • Log/event ingestion,

…Redis-backed BullMQ will outperform PostgreSQL-backed pg-boss by an order of magnitude or more.

PostgreSQL (pg-boss): Optimized for transactional semantics

PostgreSQL is a relational database with ACID transactions. For workloads where enqueueing a job must be atomic with a data change:

  • "Insert an order row and enqueue a confirmation email in the same transaction."
  • "Update a user's status and enqueue a notification atomically."
  • "Delete a record and enqueue a cleanup job together."

…pg-boss can do this natively because the job table lives in the same database:

await db.transaction(async (trx) => {
  const order = await trx.insert(orders).values({...}).returning();
  await boss.send('email', { orderId: order.id }, { db: trx });
  // If anything fails, both the order and the job are rolled back.
});

With BullMQ, you'd need a separate pattern — for example, the transactional outbox pattern, where you write jobs to an outbox table in the same transaction, and a separate process polls the outbox and enqueues to BullMQ. This works, but it's more moving parts.

Which matters more for you?

  • If you need raw throughput and your jobs are independent (retry-safe), Redis/BullMQ wins.
  • If you need transactional consistency between data writes and job enqueueing, PostgreSQL/pg-boss wins.

Most application-level job queues don't need transactional enqueueing — the cost of a missed or duplicate job is low, and at-least-once delivery with idempotent workers is sufficient. But for financial, inventory, or compliance workloads, transactional semantics can be a hard requirement.

Persistence and Durability

pg-boss (PostgreSQL)

PostgreSQL's durability is ACID and battle-tested. Once a transaction commits, the job is durable to disk (subject to synchronous_commit settings). PostgreSQL's WAL (Write-Ahead Log) ensures recovery from crashes without data loss.

BullMQ (Redis)

Redis offers two persistence mechanisms:

  • RDB (snapshotting) — periodic dumps to disk. Fast recovery; potential data loss between snapshots.
  • AOF (Append-Only File) — every write logged. More durable; slower.

Most production Redis deployments use AOF with appendfsync everysec, which can lose up to 1 second of data on crash. This is sufficient for most job queues but is not equivalent to PostgreSQL's ACID guarantees.

For workloads where losing a second of jobs is catastrophic, pg-boss has a real edge.

Throughput: Realistic Numbers

Exact numbers depend on hardware, network, payload size, and worker logic. But rough ranges:

Workload pg-boss BullMQ
Small JSON payload, trivial work ~1,000–3,000 jobs/sec ~10,000–30,000 jobs/sec
Medium payload, light DB work ~500–1,500 jobs/sec ~5,000–15,000 jobs/sec
Large payload, heavier work Bound by worker logic Bound by worker logic

At the high end, BullMQ's in-memory advantage dominates. At the low end (heavier worker logic, smaller volumes), the difference matters less.

For most application-level queues (a few hundred to a few thousand jobs/sec), either backend is sufficient. The choice should be driven by architectural fit, not raw benchmarks.

Dashboard: pg-boss vs QueueHub

pg-boss

pg-boss ships no bundled dashboard. To inspect jobs, you write SQL:

SELECT id, name, state, data, createdon
FROM pgboss.job
WHERE state = 'active'
ORDER BY createdon DESC
LIMIT 50;

This is fine for ad-hoc debugging but poor for daily operations. Teams using pg-boss typically build a custom admin panel or accept SQL-based inspection.

QueueHub

QueueHub is a hosted dashboard for BullMQ, BeeQueue, and Amazon SQS. It provides:

  • Real-time WebSocket updates — queue depth, job transitions, failure spikes.
  • Job detail viewsdata, opts, stacktrace, retry history.
  • Bulk operations — filtered retry, promote, delete, reprioritize.
  • Metrics — throughput, latency percentiles, failure rate over time.
  • SSO + RBAC + audit log — team-ready.

For teams that want a polished queue dashboard without building one, QueueHub is the answer — but it only works with BullMQ (and BeeQueue/SQS), not pg-boss.

Feature Comparison

Feature pg-boss BullMQ
Fire-and-forget jobs
Delayed jobs
Recurring jobs (cron) ✓ (schedule) ✓ (repeat.pattern)
Job priorities
Retries with backoff
Dead-letter jobs
Parent/child dependencies — (limited) ✓ (flows)
Rate limiting
Concurrency control
Transactional enqueue
Throughput Moderate High

When to Choose Each

Choose pg-boss if:

  • You already run PostgreSQL and want to avoid adding Redis.
  • You need transactional enqueueing (job + data write in one transaction).
  • Your throughput needs are modest (hundreds to low thousands of jobs/sec).
  • You're comfortable with SQL-based job inspection or building your own admin panel.
  • You value ACID durability over raw throughput.

Choose BullMQ + QueueHub if:

  • You need high throughput (thousands+ of jobs/sec).
  • You're comfortable running Redis (or already do).
  • You want a polished, hosted dashboard without building one.
  • You need multi-backend visibility (BullMQ + BeeQueue + SQS).
  • You want SSO, RBAC, and an audit log for a team.
  • Transactional enqueueing is not a hard requirement (or you're willing to use an outbox pattern).

The Transactional Outbox Pattern (For BullMQ)

If you need transactional enqueueing but prefer BullMQ's throughput and dashboarding, the transactional outbox pattern is the standard workaround:

  1. In your database transaction, write the job to an outbox table.
  2. Commit the transaction. (Now the job is durably persisted.)
  3. A separate process (the "outbox relay") polls the outbox table, enqueues jobs to BullMQ, and marks them as sent.

This adds one moving part (the relay) but gives you transactional semantics with a Redis-backed queue. It's a well-known pattern used widely in event-driven architectures.

Can You Use Both?

Yes. Some teams run pg-boss for transactional workloads (e.g., order processing) and BullMQ for high-throughput workloads (e.g., notifications, webhooks). In that case:

  • Use SQL or a custom admin panel for pg-boss.
  • Use QueueHub for BullMQ, BeeQueue, and SQS.

No single dashboard today unifies pg-boss and BullMQ.

Frequently Asked Questions

Is pg-boss slower than BullMQ?

On raw throughput benchmarks, yes — PostgreSQL has more overhead per job than Redis. For modest workloads (hundreds to low thousands of jobs/sec), the difference rarely matters. For high-throughput fire-and-forget workloads, BullMQ has a significant edge.

Can pg-boss do everything BullMQ does?

Mostly. Both cover fire-and-forget, delayed, recurring, priorities, retries, and rate limiting. BullMQ flows (parent/child dependencies) are more mature than pg-boss's equivalent patterns.

Does QueueHub monitor pg-boss?

No. QueueHub monitors BullMQ, BeeQueue, and Amazon SQS. pg-boss has no bundled dashboard; you inspect jobs via SQL or build your own.

Is Redis less durable than PostgreSQL?

Strictly, yes. PostgreSQL offers ACID durability; Redis offers configurable persistence (RDB/AOF) with potential for small data loss on crash. For most job queues, Redis durability is sufficient, but for workloads where every job must survive, PostgreSQL has the edge.

Conclusion

pg-boss and BullMQ solve the same problem (Node.js job queues) with different backend philosophies. pg-boss bets on PostgreSQL's transactional semantics and operational simplicity (one database). BullMQ bets on Redis's throughput and the maturity of its surrounding dashboard ecosystem.

If transactional enqueueing and ACID durability matter most, pg-boss is the right choice. If throughput, dashboards, and multi-backend visibility matter most, BullMQ + QueueHub is the right choice.

If you're leaning toward the latter, try QueueHub and connect your Redis in under a minute.

Related Articles