Debugging Rails Active Jobs with the Vanilla Adapters

Posted . Visible to the public.

Short reference on how to quickly debug the vanilla Rails job adapters.

Queue Adapters by Environment

Environment Adapter Jobs Run In Worker Needed?
development :async Rails server process No
test :test Not executed (stored) No
production :solid_queue Separate worker Yes (bin/jobs)

Development (:async)

Jobs run in background threads ( Concurrent Ruby ThreadPoolExecutor Show archive.org snapshot ) within the process that called the job.

  • Jobs execute immediately in a background thread within bin/rails s and write to the server logs.
  • bin/jobs does nothing in development, jobs already run in-process via :async.
  • Scripts and rake tasks log go to log/development.log

Watch out for this within the Rails or development logs:

Enqueued HelloJob (Job ID: xxx) to Async(asap)
Performing HelloJob (Job ID: xxx)
Performed HelloJob (Job ID: xxx) in 3.5s

For quick debugging, add logging or run synchronously to add a debugger:

# Skip queue, run immediately in current thread
HelloJob.perform_now(membership)

class HelloJob
  def perform
    puts "Hello" # → stdout of calling process (server or script terminal)
    Rails.logger.info "Hello" # → log/development.log (always)
    debbuger # → Work only when called within `perform_now`
  end
end

Use tail -f log/development.log or tail -f log/development.log | grep -i Hello

perform_later vs perform_now

Method Thread debugger works?
perform_later Background ❌ No, hangs waiting for input.
perform_now Main (blocking) ✅ Yes

Within perform_later the debugger will just shut down once your main process is killed or finished. Until then it will hang there waiting for input and is blocking the job.

Production (:solid_queue)

Jobs persist to solid_queue_* tables. Requires bin/jobs worker running.

# Check pending jobs
SolidQueue::ReadyExecution.count

# Check failed jobs
SolidQueue::FailedExecution.last&.error

# Find specific job
SolidQueue::Job.where(class_name: 'HelloJob').last

Test (:test)

Jobs are not executed, only stored for assertions:

assert_enqueued_with(job: HelloJob, args: [membership])

# Or execute all queued jobs
perform_enqueued_jobs do
  HelloJob.perform_later('matthew')
  assert_performed_jobs 1
end

Further Reading

Profile picture of Felix Eschey
Felix Eschey
Last edit
Felix Eschey
License
Source code in this card is licensed under the MIT License.
Posted by Felix Eschey to makandra dev (2025-12-04 15:54)