Zero bloat by design
Snapshot-based batching and TRUNCATE-based rotation instead of per-row DELETE. No dead tuples in the hot path, immune to xmin-horizon pinning. It does not slow down after months of continuous operation.
PgQ, universal edition
One SQL file to install.
A durable event stream that lives inside Postgres — a shared log with independent per-consumer cursors, closer to Kafka than to a task-message broker. Pure SQL and PL/pgSQL on any modern Postgres, managed or self-hosted. No sidecar daemon, no C extension.
\i sql/pgque.sql then select pgque.start();
SKIP LOCKED queue under sustained
load — the failure mode PgQue avoids by construction.
SKIP LOCKED. Not row claiming.
Most Postgres queues rely on SKIP LOCKED plus
DELETE and UPDATE. That holds up in toy
examples, then turns into dead tuples, VACUUM pressure, index bloat,
and performance drift under load.
PgQue uses snapshot-based batching and TRUNCATE-based rotation instead. Events become visible in batches between ticks. The hot path stays predictable, and the queue does not get slower the longer it runs.
The trade-off is end-to-end delivery latency — about a 50 ms median at the default 100 ms tick rate (p50 ≈ 52 ms), tunable down by lowering the tick period. If you need single-digit-millisecond dispatch, PgQue is the wrong tool. If you need stability under load without a bloat tax, this is where it fits.
-- one file, any Postgres 14+, managed or self-hosted\i sql/pgque.sqlselect pgque.start(); -- pg_cron ticks 10x/sec
select pgque.create_queue('orders');select pgque.subscribe('orders', 'fulfilment');select pgque.send('orders', '{"id": 42}'); -- enqueue
-- a consumer reads the current batch, then acks itselect * from pgque.receive('orders', 'fulfilment');select pgque.ack(:batch_id);Snapshot-based batching and TRUNCATE-based rotation instead of per-row DELETE. No dead tuples in the hot path, immune to xmin-horizon pinning. It does not slow down after months of continuous operation.
Pure SQL and PL/pgSQL. No C extension, no shared_preload_libraries, no daemon, no restart. Installs with \i pgque.sql on RDS, Aurora, Cloud SQL, AlloyDB, Supabase, Neon, and Crunchy Bridge.
Every consumer keeps its own cursor on one shared event log and independently receives all events. No data duplication, atomic batch boundaries, late subscribers catch up. Closer to Kafka topics than to a job queue.
ACID transactions, transactional enqueue and consume, WAL, backups, replication, SQL visibility. Wrap receive + business writes + ack in one transaction for exactly-once — a property external brokers cannot offer.
The underlying engine, PgQ, ran messaging at Skype for hundreds of millions of users for over a decade. PgQue rebuilds it for the heavy-load regime it was designed for.
Built-in retry with configurable backoff and a dead letter queue. nack with a delay to reschedule; messages route to the DLQ after max_retries. Inspect and replay from SQL.
PgQue is an event/message queue optimized for high-throughput streaming with fan-out — not a job-queue framework. The full table and notes live in the README.
| Feature | PgQue | PgQ | PGMQ | River | Que | pg-boss |
|---|---|---|---|---|---|---|
| Snapshot-based batching (no row locks) | yes | yes | no | no | no | no |
| Zero bloat under sustained load | yes | yes | no | no | no | no |
| No external daemon or worker binary | yes | no | yes | no | no | no |
| Pure SQL install, managed Postgres ready | yes | no | yes | yes | yes | yes |
| Multiple independent consumers (fan-out) | yes | yes | no | no | no | partial |
| Built-in dead letter queue | yes | no | partial | partial | no | yes |
PgQue runs on any Postgres 14+. These platforms ship pg_cron, so the automated ticker works out of the box.
Not listed? PgQue runs on any Postgres that has pg_cron 1.5 or newer.
No pg_cron at all? PgQue still works — drive the tick from any external scheduler instead.
Use the SQL API directly, or a typed client. The API is language-agnostic — everything is a function call.
Independent analysis, conversations, and coverage of PgQue in 2026.
A 47-minute deep dive into why update/delete queues degrade: SKIP LOCKED, MVCC and vacuum, snapshot-based batching, three-table rotation, and PgQue's latency trade-offs.
A concise tour of PgQue's pure-SQL installation, snapshot diff, three-table rotation, and 50–150 ms latency trade-off, followed by the week's wider Postgres news.
Install in one transaction. Tick with pg_cron. Read the ten-minute tutorial.