Skip to main content

Documentation 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.

PgQue creates three database roles at install time: pgque_reader, pgque_writer, and pgque_admin. The producer/consumer split mirrors upstream PgQ’s design — reader and writer are siblings, not parent/child — so a producer-only role cannot accidentally ack another consumer’s batch.

The three roles

RolePurposeKey grants
pgque_readerConsumers, dashboards, metricsreceive, ack, nack, subscribe, unsubscribe, get_queue_info, get_consumer_info, dlq_inspect, select on all tables
pgque_writerProducerssend, send_batch, insert_event, dlq_replay, dlq_replay_all
pgque_adminOperators, migrationsMember of both pgque_reader and pgque_writer, plus create_queue, drop_queue, set_queue_config, start, stop, ticker, maint, status
pgque_writer does not inherit pgque_reader. An app that both produces and consumes must be granted both roles explicitly. DDL-class operations (create_queue, drop_queue, start, stop, maint, maint_retry_events, ticker, force_next_tick, set_queue_config) are not granted to either pgque_reader or pgque_writer — they require pgque_admin. pgque.uninstall() is revoked from pgque_admin and PUBLIC; only the schema/install owner (typically a superuser) can run it.

Typical grant patterns

-- App that both produces and consumes — grant BOTH roles
create user app_orders with password '...';
grant pgque_reader to app_orders;
grant pgque_writer to app_orders;

-- Pure producer (e.g. a webhook ingester that only sends)
create user app_webhook with password '...';
grant pgque_writer to app_webhook;

-- Pure consumer / dashboard / metrics
create user metrics with password '...';
grant pgque_reader to metrics;

Roles are global, not per-queue

PgQue roles are coarse database-level roles. A pgque_reader can call receive, ack, and nack on any queue with any consumer name. There is no per-queue ACL built into PgQue.
What this means in practice:
  • pgque_reader gets select on all tables in the pgque schema — it can read events from any queue
  • pgque_writer can produce to any queue
  • Batch IDs are bearer tokens — a caller that learns a valid batch_id can ack it, regardless of which consumer opened it
This is intentional: the roles enforce the producer/consumer boundary, not consumer-vs-consumer isolation. If you need mutually untrusted tenants sharing one database:
  • Separate databases per tenant — connect each tenant’s application to its own database. Cleanest isolation.
  • Wrapper functions — wrap the PgQue API in app-owned stored functions that check tenant ownership before delegating to pgque.*. Grant only the wrapper functions to tenant roles.
  • Separate schemas per tenant — run separate PgQue installs in separate schemas per tenant (not yet officially supported — check the roadmap).
For trusted applications sharing one database — an internal microservices architecture, for example — the coarse role model is the right default. Add isolation only when you have a real multi-tenancy requirement.

Build docs developers (and LLMs) love