unstale

npm / pg-boss

pg-boss

What changed in pg-boss 12, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-21.

15 breaking2 deprecations12 new APIs and options1 performance11 behavior and defaults10 fixes and other

See which of these apply to your code, ranked, in your agent:

npx @unstale/cli init

@unstale/cli 0.2.1 on npm

pg-boss 1251 changes

Breaking changes 15

  • Deletes in batches and resolves to the number of jobs deleted; failures can leave a partial delete.

    12.38.0release notes

  • Deletes in batches and resolves to the number of jobs deleted; failures can leave a partial delete.

    12.38.0release notes

  • Returns matching jobs oldest first and at most 1,000 by default; callers can use limit and after to read further pages.

    12.38.0release notes

  • Reads at most limit jobs of each kind, defaulting to 1,000 and allowing up to 100,000; total is no longer exact and counts only jobs read.

    12.38.0release notes

  • After upgrading, totalCount retains its prior count until the queue's first maintenance pass, then may temporarily be off after concurrent deletes or resumes during counting.

    12.38.0release notes

  • A job naming a missing dead-letter queue now rejects with Dead letter queue <name> does not exist.

    12.37.0release notes

  • Deleting a partitioned queue no longer waits indefinitely on concurrent sends; it retries lock acquisition for about 3 seconds, then rejects and leaves the queue unchanged.

    12.37.0release notes

  • Flow creation now rejects when a queue was deleted by another instance.

    12.37.0release notes

  • Inserting into a queue deleted by another instance now rejects with Queue <name> does not exist instead of reporting nothing done.

    12.37.0release notes

  • Previously stored schedules with empty expressions are skipped by the cron pass with an invalid_schedule warning instead of firing every minute.

    12.37.0release notes

  • schedule() rejects empty, blank, or non-string cron expressions; previously an empty expression could be read as every minute.

    12.37.0release notes

  • schedule() writes on a passed db, and no longer stores db with the schedule.

    12.37.0release notes

  • Sending to a queue deleted by another instance now rejects with Queue <name> does not exist instead of resolving null; in a passed transaction, COMMIT can fail with 23503.

    12.37.0release notes

  • stop() settles in-flight claims before completing; a claim not ready within the timeout is failed without starting its handler, so shutdown can exceed timeout. With graceful: false the job is failed at once.

    12.37.0release notes

  • Upserting into a queue deleted by another instance now rejects with Queue <name> does not exist instead of resolving null or reporting nothing done.

    12.37.0release notes

Deprecations 2

  • The singletonsActive field on getQueue() and getQueues() is deprecated and will be removed in the next major.

    12.37.1release notes

  • backend: 'yugabytedb' still works but emits a Node DeprecationWarning with code PGBOSS_DEP_YUGABYTEDB and will be rejected in the next major.

    12.37.0release notes

New APIs and options 12

  • Returns at most 1,000 rows by default in version and creation order; supports limit and after paging.

    12.38.0release notes

  • Returns at most 1,000 rows by default in key order; supports limit and after paging.

    12.38.0release notes

  • Returns at most 1,000 rows by default, ordered by queue name and id; supports limit and after paging.

    12.38.0release notes

  • Returns at most 1,000 rows by default, ordered by queue name and id; supports limit and after paging.

    12.38.0release notes

  • Returns at most 1,000 rows by default, oldest first; supports limit and after paging.

    12.38.0release notes

  • Returns at most 1,000 rows by default in name order; supports limit and after paging through its options argument.

    12.38.0release notes

  • Returns at most 1,000 rows by default, ordered by queue name and key; supports limit and after paging.

    12.38.0release notes

  • An options type for bounded list reads is now exported.

    12.38.0release notes

  • The options type for previewRedrive is now exported.

    12.38.0release notes

  • getUninstallPlans(schema, { backend }) returns SQL to remove pg-boss objects from a shared schema without CASCADE.

    12.37.0release notes

  • The uninstall command prints SQL to remove pg-boss objects from a shared schema without CASCADE.

    12.37.0release notes

  • Pass attempts to retry start after database failures, waiting 1 second between tries and doubling up to 30 seconds; configuration AssertionErrors are not retried.

    12.37.0release notes

Performance 1

  • Expired jobs and orphaned dependencies are deleted a queue at a time, with each batch in its own transaction, limiting long-held locks and xmin horizons.

    12.38.0release notes

Behavior and default changes 11

  • Once a pending background command is found, pending commands run back to back; commands from one migration on one table run in order and wait for predecessors to complete.

    12.38.0release notes

  • Deletes in batches and resolves to the number of jobs deleted, or null when TRUNCATE is used; failures can leave a partial delete.

    12.38.0release notes

  • On a shared table, deletes jobs in batches before deleting the queue; a failure can leave jobs partially deleted and the queue in place.

    12.38.0release notes

  • Returns one row per status, ordered by status, without a limit.

    12.38.0release notes

  • When enabled, handler_overrun, a failed LISTEN/NOTIFY listener, and a disabled xmin_horizon check are written to the warning table.

    12.38.0release notes

  • Runs pending background migration commands after the migration commits; on failure, exits with an error listing statements left to run by hand.

    12.38.0release notes

  • Without table partitioning, old snapshots are deleted in batches on every supervise pass; with partitioning, whole days are still dropped.

    12.38.0release notes

  • The timeout now bounds how long stop waits for a running background migration command; graceful: false ends the command at once.

    12.38.0release notes

  • Expired jobs are failed in batches, so recovery after a fleet outage uses short transactions.

    12.38.0release notes

  • If a handler outlives its timeout, its worker waits for it to return before fetching again and emits a handler_overrun warning; a handler that never returns holds the worker until stopped.

    12.38.0release notes

  • unschedule() now runs its write on a passed db.

    12.37.0release notes

Fixes and other changes 10

  • A custom adapter's executeSql must return an array with one result per statement for multi-statement queries; returning only the last result breaks maintenance passes and background migration claims.

    12.38.0release notes

  • Expiry no longer deletes jobs from another queue when jobs share an id on the shared job table.

    12.38.0release notes

  • The old index now remains in place until its replacement has been built, preventing slow fetches after a failed background index build.

    12.38.0release notes

  • Multi-statement query results over postgres-js are flattened, allowing pg-boss to find rows from statements before the last.

    12.38.0release notes

  • Redriving from a dead letter queue on the shared job table now touches only that queue's jobs, avoiding deletion or in-place failure of another queue's job with the same id.

    12.38.0release notes

  • Fetches from singleton and stately queues now check whether a key has an active job instead of relying on the cached list, preventing completed-job keys from staying blocked.

    12.37.1release notes

  • A pass that loses the lock now lets the next pass count its queues, keeping counts within about one interval for getQueue(), getQueueStats(), the dashboard, queue_stats history, and large-queue warnings.

    12.37.1release notes

  • Using pg-boss before start() now reports that start() must be called, rather than naming the internal open().

    12.37.0release notes

  • publish() skips a subscribed queue deleted while it is running, unless the send ran on a passed db.

    12.37.0release notes

  • Concurrent upserts with the same singletonKey now agree on one job instead of inserting duplicates; on CockroachDB, a later upsert may fail with 40001 and is retried up to 3 times when pg-boss owns the transaction.

    12.37.0release notes