PgQue ticks on a configurable cadence. The default is 100 ms (10 checks/sec), but the true WAL cost depends on how many ticks actually materialize — idle queues back off automatically and produce negligible overhead.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.
How tick frequency works
pgque.start() schedules one 1-second pg_cron slot that calls pgque.ticker_loop(). The procedure then invokes pgque.ticker() every tick_period_ms milliseconds and commits between iterations. So sub-second ticking is real — not limited by pg_cron’s 1-second minimum schedule.
The 100 ms default is the check cadence, not a guarantee of 10 materialized ticks per second. If no events have arrived since the last tick,
ticker() returns NULL — no tick row is written. PgQue backs off idle queues toward ticker_idle_period (default 1 minute).Choosing a cadence
tick_period_ms | Check rate | Median e2e wait | Use case |
|---|---|---|---|
1000 | 1 check/sec | ~500 ms | Small projects, WAL-constrained systems, pgqd-compatible cadence |
100 (default) | 10 checks/sec | ~50 ms | Lower latency without high churn |
50 | 20 checks/sec | ~25 ms | Latency-sensitive apps (check WAL budget first) |
10 | 100 checks/sec | ~5 ms | Specialized workloads — benchmark first |
1 | 1000 checks/sec | sub-ms average | Experimental/extreme — benchmark WAL, NOTIFY, metadata churn |
WAL budget for continuously active queues
Every materialized tick writes PgQue metadata. A simple PG18 measurement isolated ~280 bytes of WAL per materialized tick per queue.| Materialized tick rate | Formula | Estimate |
|---|---|---|
| 1 tick/sec continuously | 280 B × 86,400 | ~24 MiB/day per queue |
| 10 ticks/sec continuously | 280 B × 10 × 86,400 | ~240 MiB/day per queue |
| 100 ticks/sec continuously | 280 B × 100 × 86,400 | ~2.4 GiB/day per queue |
- Full-page images —
full_page_writes = on(the default) logs full page images after checkpoints, which can exceed the steady-state estimate - Number of active queues — overhead scales with active queues, not total queues
- Scheduler logging —
cron.job_run_detailsWAL is separate; PgQue’s sub-second loop does not multiply cron log rows (still one slot per second)
Why idle queues back off
With no producer writes,pgque.ticker() consults per-queue settings before materializing a tick:
ticker_max_lag— max wall time between ticks while there is activityticker_max_count— force a tick after N eventsticker_idle_period— upper bound on idle ticking (default 1 minute)
ticker() every 100 ms is cheap when it returns NULL.
Practical recommendations
- Use
1000 msfor small projects, low-throughput queues, WAL-constrained environments, or anywhere logical replication lag matters more than sub-100 ms delivery - Monitor WAL generation, dead tuples on PgQue metadata tables, and replica lag before going below 50 ms
- For many queues in one database, estimate active queues separately; idle queues are nearly free
- If using pg_cron, schedule a log purge to avoid unbounded growth of
cron.job_run_details:
