Background Jobs with Active Job & Sidekiq
Slow work — sending email, resizing images, calling external APIs — should never block a web request. Background jobs move that work off the request cycle so your app stays fast.
Learn Background Jobs with Active Job & Sidekiq in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise…
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
By the end of this lesson you'll declare jobs with Active Job, enqueue them with perform_later, pick a backend like Sidekiq, and handle retries, scheduling, and idempotency.
What You'll Learn in This Lesson
1️⃣ Declaring and Enqueuing Jobs
An Active Job class inherits from ApplicationJob and does its work in perform . Enqueue it with perform_later so the request returns fast; perform_now runs it inline.
2️⃣ Backends, Scheduling, and Retries
Active Job is the interface; a backend actually runs the jobs. Configure one adapter ( :sidekiq , :solid_queue , and others), then use scheduling and retry declarations.
Your turn. Finish the resize job's perform body, then enqueue it asynchronously.
Mini-Challenge: An Idempotent Job
Design a scheduled NightlyReportJob that is safe to retry — re-running it for the same date must not create duplicates.
Common Errors (and the fix)
- Calling perform_now in a controller — That blocks the request; use perform_later to enqueue.
- Passing whole objects as arguments — Pass an id like user.id and re-find it inside perform .
- No worker running — With Sidekiq you must start bundle exec sidekiq or jobs sit in the queue.
- Non-idempotent jobs — Retries can double-charge or double-send; guard side effects.
- Forgetting to configure the adapter — Set config.active_job.queue_adapter or jobs run in-process only.
Pro Tips
- 💡 Keep perform small: fetch by id, do one job of work, and finish quickly.
- 💡 Use queues: queue_as separates urgent jobs from slow batch work.
- 💡 Monitor: Sidekiq ships a web dashboard to watch queues, retries, and failures.
📋 Quick Reference — Background Jobs
Concept
Rails Syntax
Define a job
class X < ApplicationJob
Enqueue (async)
X.perform_later(id)
Run now (sync)
X.perform_now(id)
Schedule
X.set(wait: 1.hour)
Retry on error
retry_on SomeError
Choose queue
queue_as :default
Frequently Asked Questions
🎉 Lesson Complete!
- ✅ Long tasks belong off the request cycle
- ✅ Jobs inherit from ApplicationJob and do work in perform
- ✅ perform_later enqueues; perform_now runs inline
- ✅ Backends like Sidekiq and Solid Queue actually run jobs
- ✅ Make jobs idempotent so retries are safe
- ✅ Next lesson: Hotwire, Turbo & Action Cable
Practice quiz
Why move slow work into a background job?
- to keep the web request fast by doing the work asynchronously
- to avoid writing tests
- to bypass routing
- to make the database larger
Answer: to keep the web request fast by doing the work asynchronously. Long tasks like email or image processing run off the request cycle so the user gets a fast response.
What is Active Job in Rails?
- a database adapter
- a templating engine
- a framework for declaring jobs and running them on various backends
- a gem for CSS
Answer: a framework for declaring jobs and running them on various backends. Active Job is a Rails framework that provides a common interface for background jobs across backends.
Which class do Active Job jobs typically inherit from?
- ActionController::Base
- ApplicationJob
- ActiveJob::Runner
- ApplicationRecord
Answer: ApplicationJob. Generated jobs inherit from ApplicationJob, which inherits from ActiveJob::Base.
Which method enqueues a job to run asynchronously?
- perform_now
- call_async
- run_background
- perform_later
Answer: perform_later. perform_later enqueues the job; perform_now would run it immediately in the current process.
What does perform_now do?
- runs the job immediately in the current process
- retries the job
- schedules the job for tomorrow
- deletes the job
Answer: runs the job immediately in the current process. perform_now executes the job synchronously right away rather than enqueuing it.
Which popular backend uses Redis to store and process jobs?
- Nginx
- Sidekiq
- SQLite
- Memcached
Answer: Sidekiq. Sidekiq is a widely used background processing library that relies on Redis.
Which newer backend stores jobs in your relational database (no Redis)?
- Resque
- Delayed Job classic
- Faktory
- Solid Queue
Answer: Solid Queue. Solid Queue is a database-backed Active Job backend, now a Rails default.
What does it mean for a job to be idempotent?
- it never fails
- it ignores arguments
- running it more than once has the same effect as running it once
- it can only run once ever
Answer: running it more than once has the same effect as running it once. An idempotent job is safe to retry because repeating it does not cause duplicate side effects.
How do you schedule a job to run later with Active Job?
- MyJob.delay(1.hour)
- MyJob.set(wait: 1.hour).perform_later
- MyJob.sleep(1.hour)
- MyJob.after(1.hour)
Answer: MyJob.set(wait: 1.hour).perform_later. set(wait: 1.hour).perform_later (or wait_until:) schedules the job for the future.
Why do background backends retry failed jobs automatically?
- to recover from transient errors like a brief network outage
- to skip validations
- to slow the app down
- to delete the queue
Answer: to recover from transient errors like a brief network outage. Automatic retries help jobs survive temporary failures; idempotency makes those retries safe.
Continue this course
- Previous: Sinatra & Rack
- Next: Hotwire, Turbo & Action Cable