Goal

You’ll understand what Active Job and background jobs solve, and be able to identify when a task genuinely belongs in a background job rather than running directly in a request.

Learn

Some tasks — sending an email, processing an image, generating a report — can take a genuinely noticeable amount of time. Running them directly inside a web request means the user’s browser sits waiting until that slow task finishes before getting any response at all.

class OrderMailerJob < ApplicationJob
  queue_as :default

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

# Enqueue it, rather than running it directly:
OrderMailerJob.perform_later(order)

perform_later adds the job to a queue, returning control to the current request immediately — the actual email sending happens separately, asynchronously, handled by a background worker process, without the user’s browser waiting for it at all.

The genuinely important distinction: perform_now runs the job’s code immediately, synchronously, blocking the current request until it finishes — functionally similar to just calling the method directly. perform_later is what actually provides the real, practical benefit of background processing, deferring the work to run separately.

A reasonable guideline for identifying background job candidates: any task that’s genuinely slow (noticeably more than a fraction of a second), and doesn’t need to complete before the user can see a response, is a good candidate. Sending a confirmation email after checkout is a textbook example — the user doesn’t need to wait for the email to actually send before seeing “Order confirmed.”

Decision Task

A checkout process sends a confirmation email synchronously, taking 3 full seconds, directly inside the request that also renders “Order confirmed” to the user. Before reading on: what real problem does this create for the user’s actual experience, and how would Active Job fix it?

Show Answer

The user’s browser sits waiting for a noticeable 3 full seconds before seeing any response at all, purely because of the email sending, even though the actual order was already successfully placed. Using OrderMailerJob.perform_later(order) instead would return control to the request immediately, letting “Order confirmed” render right away, with the actual email sending happening separately in the background, invisible to the user’s wait time.

Common Mistake

Running genuinely slow tasks (like sending emails or processing images) synchronously inside a web request, when they don’t actually need to complete before the user can see a meaningful response. This directly and unnecessarily increases how long the user has to wait, when a background job would let the response return immediately while the slow work happens separately.

Practice Questions

1. Write the code that enqueues an existing job called ReportGeneratorJob to run in the background for a given report_id.

Show Answer

ReportGeneratorJob.perform_later(report_id)

2. What’s the practical difference between perform_now and perform_later?

Show Answer

perform_now runs the job immediately and synchronously, blocking the current request; perform_later enqueues it to run separately, asynchronously, letting the current request continue immediately.

3. What real user-facing benefit does perform_later provide for a task like sending a confirmation email?

Show Answer

The user sees their response (like “Order confirmed”) immediately, without waiting for the email itself to actually finish sending in the background.

4. True or False: a background job should be used for every single task in a Rails application, regardless of how fast it is.

Show Answer

False — background jobs are genuinely useful specifically for noticeably slow tasks that don’t need to complete before the user sees a response; using them for genuinely fast tasks adds unnecessary complexity with little real benefit.

5. Name one genuinely good candidate task for a background job, and explain why, using this lesson’s guideline.

Show Answer

Sending a confirmation email — it’s noticeably slow and doesn’t need to complete before the user can see a meaningful response, matching exactly the guideline this lesson describes.

Try It Yourself

Without looking back, write a basic Active Job class called ImageProcessorJob with a perform method that takes an image and calls a hypothetical process! method on it.

Show Answer

class ImageProcessorJob < ApplicationJob\n queue_as :default\n\n def perform(image)\n image.process!\n end\nend

Quick Check

1. What problem does running a slow task directly in a web request create?

Show Answer

The user’s browser waits, unresponsive, until that slow task finishes before getting any response at all.

2. What does perform_later do, compared to perform_now?

Show Answer

Enqueues the job to run separately/asynchronously, rather than running it immediately and blocking the current request.

3. What’s a good general guideline for identifying background job candidates?

Show Answer

Genuinely slow tasks that don’t need to complete before the user can see a meaningful response.

4. Give an example of a task well-suited for a background job.

Show Answer

Sending a confirmation email (or processing an image, generating a report).

5. What must an Active Job class define, containing the actual work to be performed?

Show Answer

A perform method.

تحميل هذا الباب / Download this Chapterنسخة كاملة للدراسة بدون إنترنت، مع الأسئلة والإجابات والصور المتاحة.