Oban Background Jobs Reference
Quick reference for Elixir Oban patterns.
Oban Pro Detection
Before applying patterns, check for Oban Pro:
grep -E "oban_pro|oban_web" mix.exs grep -r "use Oban.Pro.Worker" lib/
If Oban Pro detected, see references/oban-pro-basics.md for key differences:
Standard Oban Oban Pro
use Oban.Worker
use Oban.Pro.Worker
@impl Oban.Worker
@impl Oban.Pro.Worker
def perform(%Oban.Job{})
def process(%Oban.Job{})
Oban.Testing
Oban.Pro.Testing
Pro features covered: Workflows, Batches, Structured/Recorded/Encrypted workers. See references/oban-pro-basics.md for patterns. For Pro plugins (Lifeline, Smart Engine, DynamicPrioritizer), consult oban.pro/docs.
Iron Laws — Never Violate These
-
JOBS MUST BE IDEMPOTENT — Safe to retry. Use idempotency keys for payments
-
JOBS MUST STORE IDs, NOT STRUCTS — JSON serialization. %{user_id: 1} not %{user: %User{}}
-
JOBS MUST HANDLE ALL RETURN VALUES — :ok , {:error, _} , {:cancel, _} , {:snooze, _}
-
ARGS USE STRING KEYS — Pattern match %{"user_id" => id} not %{user_id: id}
-
UNIQUE CONSTRAINTS FOR USER ACTIONS — Prevent double-click duplicates
-
NEVER STORE LARGE DATA IN ARGS — Store references (IDs, paths), not content
Quick Worker Template
defmodule MyApp.Workers.ExampleWorker do use Oban.Worker, queue: :default, max_attempts: 5, unique: [period: {5, :minutes}, keys: [:entity_id]]
@impl Oban.Worker def perform(%Oban.Job{args: %{"entity_id" => id}}) do case process(id) do {:ok, _} -> :ok {:error, :not_found} -> {:cancel, "Entity not found"} {:error, :rate_limited} -> {:snooze, {5, :minutes}} {:error, reason} -> {:error, reason} end end end
Return Value Meanings
Return State Behavior
:ok
completed
Success
{:ok, value}
completed
Success with value
{:error, reason}
retryable
Retry with backoff
{:cancel, reason}
cancelled
Stop permanently
{:snooze, seconds}
scheduled
Delay and retry
Quick Decisions
Which Queue?
-
Critical operations → High concurrency (20+)
-
Mailers/Webhooks (I/O) → Medium concurrency (30-50)
-
CPU-intensive → Low concurrency (3-5)
-
External APIs → Use dispatch_cooldown for rate limiting
Testing Pattern
use Oban.Testing, repo: MyApp.Repo
Assert enqueued
assert_enqueued worker: MyApp.Worker, args: %{id: 1}
Execute and verify
assert :ok = perform_job(MyApp.Worker, %{id: 1})
Common Anti-patterns
Wrong Right
%{user_id: id} pattern match %{"user_id" => id} (string keys)
%{user: %User{}} in args %{user_id: 1} (IDs only)
No idempotency for payments Use idempotency keys
Ignoring return values Handle all outcomes explicitly
References
For detailed patterns, see:
-
references/worker-patterns.md
-
Worker options, backoff, timeout
-
references/queue-config.md
-
Queue design, pool sizing, cron
-
references/testing-patterns.md
-
Testing, assertions, drain