Queue Configuration
This guide explains how to configure async-job queue definitions, route Active Jobs, and adopt the adapter incrementally.
Overview
Active Job assigns every job a queue name. The adapter must map that name to an async-job queue definition, which specifies the processor responsible for storing and running the job.
The adapter includes a default definition backed by Async::Job::Processor::Inline. Define additional queues when you need:
- A shared processor such as Redis instead of in-process execution.
- Separate capacity for latency-sensitive and bulk workloads.
- Several Active Job queue names routed through one processor.
Every name selected by queue_as must have a matching definition or alias.
Defining a Queue
Queue definitions belong in config/initializers/async_job.rb. The examples below use the Redis processor so independently operated queues have shared storage:
$ bundle add async-job-processor-redis
This definition replaces the built-in inline default queue:
require "async/job/processor/redis"
Rails.application.configure do
config.async_job.define_queue "default" do
dequeue Async::Job::Processor::Redis
end
end
Processors can accept positional and keyword arguments after the processor class.
Redis Endpoints
Without an explicit endpoint, the Redis processor connects to redis://localhost:6379. Pass an Async::Redis::Endpoint when Redis runs on another host, requires credentials, uses a different database, or accepts TLS connections:
redis_endpoint = Async::Redis::Endpoint.parse(ENV.fetch("REDIS_URL"))
Rails.application.configure do
config.async_job.define_queue "default" do
dequeue Async::Job::Processor::Redis, endpoint: redis_endpoint
end
end
REDIS_URL may use either the redis:// or rediss:// scheme and can include credentials, a port, and a database number, for example redis://username:password@redis.example.com:6379/1. Keep credentials in the environment rather than writing them into the initializer.
The bundled worker loads the Rails environment, so Rails and worker processes use the same queue definition. Ensure REDIS_URL is present and identical in both process environments.
Redis Prefixes
Without an explicit prefix, every Redis processor uses async-job. Queue definition names do not alter that default, so two definitions using the same Redis endpoint and prefix operate on the same underlying queue.
For each independently processed queue, the prefix must be:
- Distinct from other queues using the same Redis endpoint.
- Identical in Rails and worker processes.
- Stable across deployments so existing jobs remain reachable.
Include an application or environment namespace only when those workloads share a Redis endpoint.
Defining Multiple Queues
Multiple definitions allow independent worker groups to process different workloads. For example, payment capture can use a dedicated queue while ordinary work remains on default:
require "async/job/processor/redis"
Rails.application.configure do
config.async_job.define_queue "default" do
dequeue Async::Job::Processor::Redis, prefix: "async-job:default"
end
config.async_job.define_queue "critical" do
dequeue Async::Job::Processor::Redis, prefix: "async-job:critical"
end
end
Select the definition using the standard Active Job API:
class PaymentCaptureJob < ApplicationJob
queue_as :critical
retry_on PaymentGateway::Unavailable, wait: 5.seconds, attempts: 5
discard_on ActiveRecord::RecordNotFound
def perform(payment_id)
Payment.find(payment_id).capture!
end
end
Create separate definitions only when workloads need distinct storage, capacity, or operational controls. A single definition is simpler when those differences do not matter.
Aliasing Queue Names
Aliases route several Active Job queue names through one queue definition. This is useful for framework-defined names such as mailers when they do not need independent worker capacity:
Rails.application.configure do
config.async_job.alias_queue "default", "mailers", "low_priority"
end
Jobs assigned to mailers or low_priority are submitted through the default definition. Aliases do not create queues and are not valid values for ASYNC_JOB_ADAPTER_ACTIVE_JOB_QUEUE_NAMES; worker selection uses definition names.
Opting In One Job at a Time
Applications can adopt the adapter without replacing their global Active Job backend. Set queue_adapter on an individual job and leave other jobs unchanged:
class SearchIndexRefreshJob < ApplicationJob
self.queue_adapter = :async_job
queue_as :default
retry_on SearchIndex::Unavailable, wait: 5.seconds, attempts: 3
discard_on ActiveRecord::RecordNotFound
def perform(product_id)
Product.find(product_id).refresh_search_index!
end
end
The selected queue must still have a definition or alias in config.async_job.
Understanding the Pipeline
When perform_later is called, class ActiveJob::QueueAdapters::AsyncJobAdapter serializes the Active Job and sends it to the definition selected by queue_as. The configured processor transports or schedules the payload. On the consumer side, class Async::Job::Adapter::ActiveJob::Executor deserializes it and invokes Active Job.
Definitions use async-job's pipeline builder. The processor is written as dequeue because it wraps the consumer side of the pipeline; it still supplies the client used by Rails to enqueue jobs. The Active Job executor is appended automatically and should not be added to the definition.