Skip to content

12.30.0

Latest

Choose a tag to compare

@timgit timgit released this 03 Sep 15:56
· 20 commits to master since this release
180a54b

What's Changed

Schema version: 40 (a migration runs on upgrade — see Upgrading).

Fetch is now an ordered index walk instead of a sort, and maintenance reports when vacuum has stopped keeping up with the queues. Options priority and orderByCreatedOn are now deprecated.

Highlights

The fetch index matches the fetch

The fetch orders by priority desc, created_on, but the index led with start_after, so every poll read all eligible rows and sorted them. On a 500k-row job table that is a top-N heapsort over 5,257 buffers:

Limit (actual time=44.880..47.794 rows=1)
  Buffers: shared hit=5257
  ->  Sort  Sort Key: priority DESC, created_on
        Sort Method: top-N heapsort

The index now leads with the sort keys and keeps start_after as a trailing key column, so the same fetch is an ordered walk that stops at the first row:

Limit (actual time=0.079..0.080 rows=1)
  Buffers: shared hit=16
  ->  Index Scan using job_common_i11
        Index Cond: ((name = 'q') AND (start_after < now()))

47.8 ms → 0.11 ms, 5,257 buffers → 16. Cost is 27% more index (15 MB → 19 MB at 500k rows).

priority and orderByCreatedOn are deprecated

Both of these options were created to optimize perf, based on the previous index. As of this release, they are ignored and will be rejected in the next major. Jobs are always fetched in priority and creation order.

// no longer changes anything, and emits a DeprecationWarning once per option per instance
await boss.fetch('my-queue', { priority: false })
(node:1234) [PGBOSS_DEP_FETCH_SORT] DeprecationWarning: priority: false is deprecated and now ignored

Run with --trace-deprecation to find the call site, or --throw-deprecation to fail a build on it. It is a Node deprecation rather than a pg-boss warning event, which stays reserved for database and queue health.

If you set priority: false for throughput, remove it: it was measured roughly 180x slower than the default, since no index leads with created_on.

Vacuum health is monitored

A primary failure pattern of Postgres-hosted queues is a busy server that is unable to perform maintenance via autovacuum. Until now pg-boss reported a symptom via a warning about a queue's backlog, but the remedy for this wasn't clear. One easy solution to this warning is to increase workers, concurrency, or batch size. If the actual cause was related to a busy server, adding more polling workers or increasing busyness could instead make this issue worse, or at best not improve anything.

Maintenance now measures autovacuum configuration and adds a couple of new warnings:

warning what it means the fix
xmin_horizon vacuum runs and reclaims nothing find and release whatever is pinning the horizon
autovacuum_disabled nothing is vacuuming the table at all turn autovacuum back on, or vacuum on a schedule that keeps up

xmin_horizon names the holder — an idle-in-transaction backend, a replication slot, a standby with hot_standby_feedback, a prepared transaction — including its pid, application_name and role where the connected role is allowed to read them, and whether it is your own connection or another application. Catalogs the role cannot read are listed in unreadableSources, so a partial answer is never reported as a clean one.

const boss = new PgBoss({ connectionString }) // monitorVacuum: true
const boss = new PgBoss({ connectionString, monitorVacuum: false })

Vacuum monitoring is on by default, so an installation whose horizon is already pinned will warn on the second maintenance pass after upgrading. Set monitorVacuum: false to turn it off.

Queue monitoring backs off before it starves autovacuum

Queue stats are periodically calculated via monitoring, and this requires count aggregate queries that survey the whole job table. Under high job load, or if the job table retention policy is not removing jobs fast enough, this query has the capability of becoming it's own issue, as long-running queries hold a transaction snapshot that Postgres will not vacuum past. Now, monitoring is itself "monitored", and if it spends more than a tenth of autovacuum_naptime scanning, it will start to back off long enough for an autovacuum worker to get a clean window. If this happens, a monitor_backoff warning will be emitted.

Upgrading

Schema 40 adds two nullable columns (version.monitor_backoff_on, queue.monitor_claim_on).

The fetch index is replaced. job_i5 is retired and job_i11 takes its place. The new index is built with CREATE INDEX CONCURRENTLY in the background before the old one is dropped.

Full Changelog: 12.29.0...12.30.0