Guide

# ActiveJob adapter

Set the adapter to :pgbus and your existing jobs run on PGMQ, unchanged.

## Set the adapter

pgbus is a standard ActiveJob queue adapter. Point Rails at it and every job in your app enqueues through PGMQ:

```ruby
config.active_job.queue_adapter = :pgbus
```

> **Note:** Because it's a standard adapter, nothing about your job classes changes — no base-class swap, no per-job include. `queue_as`, `retry_on`, and `discard_on` all work as usual.

## Enqueue and schedule

Your existing jobs work with no edits:

```ruby
class OrderConfirmationJob < ApplicationJob
  queue_as :mailers

  def perform(order)
    OrderMailer.confirmation(order).deliver_now
  end
end

OrderConfirmationJob.perform_later(order)                    # enqueue now
OrderConfirmationJob.set(wait: 5.minutes).perform_later(order) # scheduled
```

A scheduled job is sent with a PGMQ delay, so it stays invisible until its time arrives — no separate scheduler poll table.

## What happens to a message

Enqueue, read, execute, archive — or dead-letter.

Each job becomes one PGMQ message. The adapter serializes it to JSON and sends it to the queue; a worker claims it under a visibility timeout, runs it inside the Rails executor, and archives it on success. On failure the visibility timeout expires and the message is retried — until `read_ct` crosses `max_retries`, when it routes to the dead-letter queue.

send_message

→ q_<queue>

read (worker)

vt: message hidden

read_batch

archive → a_<queue>

success

perform_now ok

raise → vt expires, read_ct++

<queue>_dlq

read_ct > max_retries

give up

Success archives the message; repeated failures raise read_ct until it crosses max_retries and routes to the DLQ.

The retry backoff and dead-letter details are on [Retries & dead letters](https://pgbus.zoolutions.llc/docs/retries-dead-letters).

## Serialization and safety

Payloads are **JSON only** — pgbus never uses `Marshal`, so a malicious or corrupt payload can't deserialize into arbitrary Ruby. GlobalID arguments (an Active Record record) resolve the same way they do under any adapter.

> **Tip:** Need at-most-once semantics or a concurrency cap? See [Concurrency & uniqueness](https://pgbus.zoolutions.llc/docs/concurrency-uniqueness) — `ensures_uniqueness` and `limits_concurrency` layer straight onto a job class.