This guide walks the full PgQue message loop — create a queue, send an event, advance the queue, receive the batch, and acknowledge it. All examples use plain SQL and work against any Postgres 14+ instance. You will needDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/NikolayS/PgQue/llms.txt
Use this file to discover all available pages before exploring further.
psql and a database with PgQue installed.
The snapshot rule.
send, ticker, and receive must each run in their own committed transaction. This is a hard requirement of PgQ’s snapshot-based design, not a recommendation. The ticker captures a snapshot of committed transaction IDs; an event that was sent in the same transaction as the tick is still in-progress at that moment and gets excluded from the batch’s visibility window, so it never surfaces to consumers. In psql with autocommit enabled (the default), each select statement is its own transaction — do not wrap the steps below in a single begin/commit block.Install PgQue
If you have not installed PgQue yet, follow the installation guide. Come back here once
select pgque.version(); returns a version string.Create a queue and consumer
A queue is a named, shared event log. A consumer is a named cursor into that log. Any number of producers can write to the same queue concurrently, and any number of consumers can subscribe — each sees every event independently (fan-out by default).
create_queue returns 1 when it creates the queue and 0 if the queue already existed — the call is idempotent. subscribe is the modern alias for register_consumer.Send a message
Send one event to the queue. The The return value is the event id — unique within the queue, monotonically increasing within a rotation window. If you call
jsonb overload validates and canonicalizes the payload before storing it.receive right now you will get zero rows, because no tick has run yet and no batch boundary exists. Continue to the next step.Advance the queue
PgQue is tick-based, not row-claiming. Consumers do not see events directly — they see batches. A batch is the set of events between two consecutive ticks. Until a tick runs, there is no batch boundary and
receive has nothing to return.In production, pg_cron or an external scheduler drives ticks automatically. For demos, tests, and manual operation, use force_next_tick to bypass the tick thresholds for one queue, then call ticker() to materialise the tick.force_next_tick bumps the event-sequence threshold so the next ticker() call creates a tick even if the normal count/lag thresholds have not been reached. ticker() returns the number of queues it processed.Receive the batch
Now pull the batch. Each returned row is a
pgque.message composite carrying msg_id, batch_id, type, payload, retry_count, created_at, and four free-form extra1..4 columns.retry_count is NULL on first delivery. The batch_id is what you need for the next step. Every row in a batch carries the same batch_id.Note that payload is stored as text; cast to jsonb for JSON field access: (payload::jsonb)->>'order_id'.Acknowledge the batch
A batch stays assigned to the consumer until it calls Or, if you already know
ack. Until then, the same batch is returned every time you call receive — the consumer has not moved its cursor forward.Capture the batch_id from the previous step and acknowledge it. In psql, \gset is the ergonomic way:batch_id = 1 from the output above:ack returns 1 on success. After acking, receive returns zero rows — the consumer’s cursor has advanced past the batch.In application code, capture batch_id from any row returned by receive and pass it to ack once all events in the batch are processed.Complete example
Here is the full loop in one block for reference. Each statement is a separate transaction in psql autocommit.Next steps
Fan-out
Register multiple consumers on the same queue and deliver every event to each independently.
Retry and dead letter queue
Use
nack to schedule retries and route exhausted messages to the DLQ.Ticker and scheduling
Configure pg_cron, pg_timetable, or an external scheduler for production use.
Roles and security
Understand the producer/consumer role split and grant access safely.
