Skip to content
cccskills
FreePublished on GitHub

oban

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.

The English summary is being prepared. Showing the original description.

See how to install

Files included (5)

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

SKILL.md (original)

Review the instructions the agent will receive before you install.

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/
grep -r "Oban.Pro.Engines.Smart" config/

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

Standard ObanOban Pro
use Oban.Workeruse Oban.Pro.Worker
def perform(%Job{})def process(%Job{})
Oban.TestingOban.Pro.Testing
Advisory lock engineOban.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 ${CLAUDE_SKILL_DIR}/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

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

ReturnStateBehavior
:okcompletedSuccess
{:ok, value}completedSuccess with value
{:error, reason}retryableRetry with backoff
{:cancel, reason}cancelledStop permanently
{:snooze, seconds}scheduledDelay 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

WrongRight
%{user_id: id} pattern match%{"user_id" => id} (string keys)
%{user: %User{}} in args%{user_id: 1} (IDs only)
No idempotency for paymentsUse idempotency keys
Ignoring return valuesHandle all outcomes explicitly

References

For detailed patterns, see:

  • ${CLAUDE_SKILL_DIR}/references/worker-patterns.md - Worker options, backoff, timeout
  • ${CLAUDE_SKILL_DIR}/references/queue-config.md - Queue design, pool sizing, cron, Smart Engine
  • ${CLAUDE_SKILL_DIR}/references/testing-patterns.md - Testing, assertions, drain (OSS + Pro)
  • ${CLAUDE_SKILL_DIR}/references/oban-pro-basics.md - Pro.Worker, Workflow, Batch, Chunk, Relay, plugins

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Analyze a legacy app in any language before rewriting it in Elixir: inventory, features as goals, why each mechanism exists, runtime topology, external contracts. Use to start or refresh a rewrite.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 20, 2026

Design the idiomatic Elixir architecture for a rewrite: set the compatibility bar (ADR-000), consult phx specialists on open questions, then build contexts, ledger and ADRs. Use after /rewrite:analyze.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 20, 2026

Ash Framework — resources, actions, policies, aggregates, calculations, AshPhoenix.Form, LiveView, migrations. Use when generating resources via mix ash.codegen, editing changes, checks, types, validations, or domain code interfaces.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 20, 2026

Ash Framework — resources, actions, policies, aggregates; Use when generating resources via mix ash.codegen, editing…

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 20, 2026

Compatibility alias for the Elixir/Phoenix plugin's LiveView assigns audit. Invoke explicitly with /lv:assigns.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 20, 2026

Inspect LiveView socket assigns for memory bloat — missing temporary_assigns, unused assigns, unbounded lists needing streams, memory estimates. Use when LiveView memory grows or you need to add temporary_assigns.

The English summary is being prepared. Showing the original description.

oliver-kriska/claude-elixir-phoenix567Updated Oct 20, 2026

See all skills by oliver-kriska

Report a problem with this skill