Skip to content
Back to skills

Oban

ASecurity

'Use when writing, scheduling, testing or debugging Oban jobs, even for

  • 559 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 5, 2026
ai-agentsbashawstestingdebuggingapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add oliver-kriska/claude-elixir-phoenix --skill oban --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Oban?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Oban
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/oliver-kriska-oban-claude-elixir-phoenix/badge)](https://www.skillsdirectory.com/skills/oliver-kriska-oban-claude-elixir-phoenix)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: oban
description: 'Use when writing, scheduling, testing or debugging Oban jobs, even for
  a how-to question: workers, cron, retries, unique jobs, queues, Pro Workflow/Batch.
  Load it before touching job code; it holds the job rules.'
---

# Oban Background Jobs Reference

Quick reference for Elixir Oban patterns.

## Oban Pro Detection

**Before applying patterns, check for Oban Pro:**

```bash
grep -E "oban_pro|oban_web" mix.exs
grep -r "use Oban.Pro.Worker" lib/
grep -r "Oban.Pro.Engines.Smart" config/
```

**If Oban Pro detected**, use Pro patterns for ALL new workers:

| Standard Oban | Oban Pro |
|---------------|----------|
| `use Oban.Worker` | `use Oban.Pro.Worker` |
| `def perform(%Job{})` | `def process(%Job{})` |
| `Oban.Testing` | `Oban.Pro.Testing` |
| Advisory lock engine | `Oban.Pro.Engines.Smart` |

**Pro features** (all optional): `args_schema` (typed args), Workflows, Batches, Chunks,
Relay, hooks, encryption, deadlines, chaining, Smart Engine (global concurrency + rate limiting).
Pro plugins (DynamicCron, DynamicLifeline, DynamicPruner) **enhance** OSS equivalents — swap module, don't run both.
See `references/oban-pro-basics.md` for all patterns and migration guide.

---

## Iron Laws — Never Violate These

1. **JOBS MUST BE IDEMPOTENT** — Safe to retry. Use idempotency keys for payments
2. **JOBS MUST STORE IDs, NOT STRUCTS** — JSON serialization. `%{user_id: 1}` not `%{user: %User{}}`
3. **JOBS MUST HANDLE ALL RETURN VALUES** — `:ok`, `{:error, _}`, `{:cancel, _}`, `{:snooze, _}`
4. **ARGS USE STRING KEYS** — Pattern match `%{"user_id" => id}` not `%{user_id: id}`
5. **UNIQUE CONSTRAINTS FOR USER ACTIONS** — Prevent double-click duplicates
6. **NEVER STORE LARGE DATA IN ARGS** — Store references (IDs, paths), not content
7. **SMART ENGINE: NEVER USE `attempt` TO LIMIT SNOOZES** — Snooze rolls back attempt counter. Use `meta["snoozed"]` instead. Causes infinite loops

## Quick Worker Template

```elixir
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

```elixir
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, Smart Engine
- `references/testing-patterns.md` - Testing, assertions, drain (OSS + Pro)
- `references/oban-pro-basics.md` - Pro.Worker, Workflow, Batch, Chunk, Relay, plugins

Files in this skill

  • SKILL.md3.9 KB
  • references/oban-pro-basics.md9.7 KB
  • references/queue-config.md2.8 KB
  • references/testing-patterns.md2.9 KB
  • references/worker-patterns.md3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.