QueueKeeper
Oban jobs fail quietly. Find out before your users do.
A stalled queue, a job that never finishes, or a worker discarding jobs after its last retry usually raises no error. QueueKeeper is a free, read-only check that looks for these failures in your oban_jobs table and tells you which queue and worker is affected.
The check is open source (MIT) on GitHub. Hosted alerting isn't built yet.
What the free check looks for
Overdue jobs and nothing attempted recently: the queue isn't running, is paused, or leadership is broken (or every slot is busy with long-running jobs).
Jobs executing past the time budget you set per worker. Duration metrics miss these because the jobs haven't finished yet.
Jobs in executing far longer than anything should run. It measures execution age only: the job may have been orphaned by a node crash, or may still be running.
Too many due jobs in a queue, or the oldest one has waited too long. One depth and one wait threshold, applied to every queue.
Many jobs of one worker failing and being retried within a short window.
Jobs that ran out of attempts or were cancelled. These fail silently unless something looks.
An expected worker hasn't had a job inserted for longer than you allow.
How it works
$ mix queue_keeper.check --repo MyApp.Repo
WARNING: 1 Oban queue problem(s) at 2026-10-22T05:09:00Z
- [warning] discarded queue=failing worker=DemoApp.Workers.Doomed:
7 job(s) exhausted their attempts or were discarded in the
last 3600s (limit 5). These fail silently unless something
alerts on them.
Output from our demo app with default thresholds (shortened).
- Runs aggregate SQL queries on
oban_jobs. It never reads job args and sends nothing anywhere. - Exits 0 (ok), 1 (warning), 2 (critical) or 3 (the check itself couldn't run), so cron, CI or your existing alerting can act on it. Also callable from Elixir, with JSON and Slack-payload output.
- Run it from an Oban cron job, or from system cron via your release so it still works when Oban itself is down.
- Tested with Oban 2.24 on PostgreSQL 17, SQLite and MySQL 8.4. Not tested with Oban Pro.
- Early version (0.2.1), on Hex as
{:queue_keeper_check, "~> 0.2.1"}. Every check's thresholds are configurable; hanging-job budgets can be set per worker.
Hosted alerting (planned)
A check you run yourself still needs something to notice when it stops running. We're exploring a small hosted service that would:
- receive check results (aggregate counts only, never job args),
- alert you in Slack or email when a check fails, and when check-ins stop arriving,
- keep a short history so you can see when a queue started falling behind.
None of this exists yet, and pricing isn't set. If it would help you, join the waitlist and tell us what hurts. We read every reply.
Join the waitlist
Privacy: we only store your email (and anything you choose to add above, plus your country) to contact you about QueueKeeper. No trackers or third-party scripts on this site. To unsubscribe or have your details deleted, email hello@queuekeeper.dev.
FAQ
Is QueueKeeper affiliated with Oban?
No. It's an independent project from Titanium Monkey Labs and isn't affiliated with or endorsed by Oban or Oban Pro.
Does it read my job data?
No. The check runs aggregate queries over timestamps, states, queue and worker names, and reports a few sample job ids. Job args are never read, and the library makes no network calls.
Is the check really free?
Yes. It's MIT licensed, so you can use, modify and keep it for free. The planned hosted alerting would be a paid service; you won't need it to use the check.
What if Oban itself is down?
A check that runs inside Oban can't report that Oban is down. Run it from system cron through your release instead, and ping a dead-man's-switch service after each run so a missing run gets noticed too.
I use Oban's Pruner. Does that matter?
Yes, for some checks. The Pruner deletes completed, cancelled and discarded jobs (by default after 60 seconds), which hides spikes and old cron runs. Shrink the check windows to fit what your Pruner keeps, or set its max_age to cover your longest window.
When will hosted alerting be ready?
We don't have a date. We'll build it if enough teams want it, and waitlist members will hear first.