Skip to content

Ror Background Jobs

DodaTech 4 min read

title: Ruby on Rails Background Jobs — Complete Guide to Active Job description: 'Learn Ruby on Rails background jobs: Active Job, Sidekiq, Solid Queue, job scheduling, mailer delivery, recurring jobs, and monitoring with Sidekiq UI.' date: 2026-06-28 lastmod: 2026-06-28 weight: 29 tags: [backend, ror]


Rails background jobs handle time-consuming tasks (email, file processing, API calls) asynchronously using Active Job with backends like Sidekiq (Redis) or SolidQueue (database).

## What You'll Learn

By the end of this tutorial, you'll create and enqueue jobs, configure Sidekiq and SolidQueue, schedule recurring jobs, handle failures with retries, and monitor job queues.

## Real-World Use

An e-commerce app processes order confirmations, generates PDF invoices, syncs inventory with warehouse systems, and sends weekly analytics emails — all via background jobs.

## Background Jobs Learning Path

```mermaid
flowchart LR
  A[Mailers] --> B[Background Jobs]
  B --> C[Caching]
  C --> D[Security]
  D --> E[Docker]
  B --> F{You Are Here}
  style F fill:#f90,color:#fff

Creating a Job

rails generate job process_payment
rails generate job send_welcome_email
# Creates app/jobs/application_job.rb and app/jobs/*_job.rb
# app/jobs/process_payment_job.rb
class ProcessPaymentJob < ApplicationJob
  queue_as :default
  retry_on PaymentGatewayError, wait: :polynomially_longer, attempts: 5
  discard_on InvalidPaymentError

  def perform(order_id)
    order = Order.find(order_id)
    service = PaymentService.new(order)
    result = service.charge!

    if result.success?
      OrderMailer.payment_confirmation(order).deliver_now
      order.update!(paid_at: Time.current)
    else
      raise PaymentGatewayError, result.error_message
    end
  end
end

Enqueuing Jobs

# From controller
class OrdersController < ApplicationController
  def create
    @order = Order.new(order_params)
    if @order.save
      ProcessPaymentJob.perform_later(@order.id)          # Default queue
      ProcessPaymentJob.set(wait: 1.hour).perform_later(id)  # Delayed
      ProcessPaymentJob.set(queue: :urgent).perform_later(id) # Different queue
      SendWelcomeEmailJob.perform_later(@order.user)
      redirect_to @order, notice: "Order placed!"
    end
  end
end

# Set priority globally
class ApplicationJob < ActiveJob::Base
  sidekiq_options retry: 5, queue: :default
end

Sidekiq Setup

# Gemfile
gem "sidekiq"
gem "sidekiq-cron"  # Recurring jobs
# config/routes.rb
require "sidekiq/web"
Rails.application.routes.draw do
  mount Sidekiq::Web => "/sidekiq"  # Job monitoring dashboard
end

# config/routes.rb (with auth)
authenticate :user, ->(u) { u.admin? } do
  mount Sidekiq::Web => "/sidekiq"
end
# config/application.rb
config.active_job.queue_adapter = :sidekiq
# config/sidekiq.yml
:concurrency: 5
:queues:
  - [critical, 5]
  - [default, 3]
  - [mailers, 2]
  - [low, 1]
# Run Sidekiq worker
bundle exec sidekiq
# Visit /sidekiq for dashboard

Recurring Jobs

# config/initializers/sidekiq_cron.rb
Sidekiq::Cron::Job.create(
  name: "Weekly report",
  cron: "0 9 * * 1",  # Every Monday 9 AM
  class: "WeeklyReportJob"
)

Sidekiq::Cron::Job.create(
  name: "Cleanup expired sessions",
  cron: "0 0 * * *",   # Every midnight
  class: "CleanupSessionsJob"
)
# app/jobs/weekly_report_job.rb
class WeeklyReportJob < ApplicationJob
  queue_as :low

  def perform
    User.find_each do |user|
      WeeklyReportMailer.report(user).deliver_later
    end
  end
end

Solid Queue (Database Backend)

# Gemfile (Rails 8 default)
gem "solid_queue"
# config/application.rb
config.active_job.queue_adapter = :solid_queue
# config/solid_queue.yml
default: &default
  dispatcher:
    polling_interval: 1
    batch_size: 500
  worker:
    queues:
      - [critical, 5]
      - [default, 3]
      - [mailers, 1]
development:
  <<: *default
production:
  <<: *default
# Install and run
rails solid_queue:install
bundle exec rake solid_queue:work

Common Mistakes

1. Passing Complex Objects to Jobs

Pass record IDs (user.id) not objects (user). Jobs serialize arguments as JSON.

2. Jobs That Are Too Large

A job should do one thing. If a job has multiple responsibilities, split it.

3. Not Handling Failures

Without retry_on, failed jobs are lost. Always configure retry policies.

4. Ignoring Queue Priorities

All jobs in the default queue causes delays. Use multiple queues with priorities.

5. Not Monitoring Jobs

Without monitoring (Sidekiq UI or Solid Queue dashboard), silent failures go unnoticed.

Practice Questions

1. What is Active Job?

Rails' standard interface for background jobs. Works with various backends (Sidekiq, SolidQueue, Delayed Job).

2. How do you delay job execution?

Use .set(wait: 1.hour).perform_later or .set(wait_until: Date.tomorrow.noon).perform_later.

3. What is the difference between Sidekiq and Solid Queue?

Sidekiq uses Redis (faster, more features). Solid Queue uses the database (simpler, no Redis dependency).

4. How do you handle job failures?

Use retry_on for retryable errors, discard_on for permanent failures, and rescue for error logging.

5. Challenge: Create a job that processes weekly email reports and retries 3 times on failure.

class WeeklyDigestJob < ApplicationJob
  queue_as :low
  retry_on Net::SMTPError, wait: 5.minutes, attempts: 3

  def perform
    User.active.find_each do |user|
      DigestMailer.weekly(user).deliver_later
    end
  end
end

FAQ

Should I use Sidekiq or Solid Queue?

Sidekiq for high-volume apps needing Redis. Solid Queue for simplicity (Rails 8 default, no Redis needed).

How do I test background jobs?

Use perform_enqueued_jobs in tests or assert_enqueued_with to verify a job was queued.

What happens if a job fails repeatedly?

Jobs exhaust retries and move to the dead set (Sidekiq) or fail permanently. Monitor and alert.

Can I schedule recurring jobs?

Yes. Use sidekiq-cron, whenever gem, or Solid Queue's recurring schedule.

How do I pass complex arguments to jobs?

Pass IDs and let the job load records from the database. Avoid passing Active Record objects.

Mini Project: Background Email Job

Create a job that sends welcome emails in the background with Sidekiq.

rails generate job send_welcome_email
# Implement perform(user_id)
# Enqueue from UsersController create action
# Start Sidekiq: bundle exec sidekiq
class SendWelcomeEmailJob < ApplicationJob
  queue_as :mailers
  def perform(user_id)
    user = User.find(user_id)
    UserMailer.welcome(user).deliver_now
  end
end

What's Next

Ruby on Rails Caching Ruby on Rails Security

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro