Changelog for Oban v2.21
View Source🌟 Looking for changes to Oban Pro? Check the Oban.Pro Changelog 🌟
This release requires PostgreSQL 14+, adds a new suspended job state, includes targeted
performance improvements for job execution and notifications, and a variety of bug fixes.
See the Upgrade Guide for upgrade instructions.
🚟 Suspended State
The new suspended state allows jobs to be held without processing until they are explicitly
resumed. Unlike scheduled jobs that become available when their time comes, suspended jobs
remain paused indefinitely until an external action resumes them.
While Oban itself doesn't make use of suspended jobs, the state enables Pro workflows to defer execution without any workarounds or performance impact.
See the Upgrade Guide for details on migrating.
📏 Performance Tweaks
Two targeted optimizations reduce overhead in high-throughput systems:
Selective Compression — Notifications under 512 bytes skip gzip compression entirely, avoiding CPU overhead for typical small messages like queue signals and insert events. Encoding is 12x faster for small payloads (4μs → 0.3μs) and wire size is halved (80 → 41 bytes). Large payloads still compress with no regression.
Batched Process Metrics — Job execution telemetry now gathers memory and reduction metrics in a single
Process.info/2call instead of two separate calls, cutting per-job measurement overhead in half.
v2.21.0 — 2026-03-25
Changes
[Oban] Support a minimum of PostgreSQL 14+
PG 12 was end of life in November 2024, and PG 13 was end of life in November 2025. We now support PG 14+, and with PG 19 due out in a few months, we're dropping official support for older versions.
Enhancements
[Oban] Add suspended job state
The suspended state allows jobs to be held without processing until they are explicitly resumed. It is accepted for unique and replace operations, and is part of the incomplete state group. The suspended state is used by Pro extensions rather than by Oban itself.
[Worker] Elevate
__opts__/0to a documented callbackThe
__opts__/0function, which returns a worker's compile-time options, is now a public callback with full documentation. This makes it easier to introspect worker configuration at runtime, such as checking the default queue, max attempts, or uniqueness settings for any worker module.[Period] Document and publicize
Oban.PeriodmoduleThe
t:Period.t()type is referenced by several public types and should be visible to users in documentation.[Executor] Batch process info calls in executor measurements
Reduces system call overhead by combining separate memory and reductions queries into a single
Process.info/2call per job execution.[Notifier] Skip compression for small notification payloads
Notifications under 512 bytes are sent as plain JSON, avoiding gzip overhead for typical small messages like queue signals and insert events.
Encode is 12x faster for small payloads (4.08 μs → 0.34 μs) and decode is 6.7x faster (1.78 μs → 0.26 μs). Wire size is halved (80 → 41 bytes).
Large payloads retain compression with no performance regression.
[Notifier] Remove wrapper from notifier LISTEN/UNLISTEN
SimpleConnection uses the simple query protocol which handles multiple semicolon-separated statements directly, eliminating the need for a
DO $$BEGIN ... END$$anonymous block. This makes the Postgres notifier more compatible with Postgres-compatible databases like PlanetScale.
Bug Fixes
[Testing] Support snooze periods with testing helpers
The
perform_job/3helper wasn't aware of snooze periods and considered snoozing with a period an error.[Oban] Correct type checking for
insert_all/3streamsSome stream functions return a multi arity function rather than a Struct. This updates the
Oban.insert_allguard to handle all stream variants properly. Thanks Elixir 1.20![Notifier] Fix Sonar and Midwife listener loss after Notifier crash
Both Sonar and Midwife register as listeners on the Notifier during init, but under the one_for_one supervisor strategy, a Notifier crash only restarts the Notifier rather than any siblings. The new Notifier starts with an empty listener map, silently breaking notification delivery.
For Sonar, this means pings are sent but never received back, causing it to degrade to :isolated status. For Midwife, signal notifications (queue start/stop) are never delivered.
[Stager] Protect from Notifier crash during staging
Prevent an exit from a dead or dying Notifier from cascading into a Stager crash.
[Job] Update
t:unique_option/0to support state groups