Fix: Sidekiq Jobs Not Processing — Troubleshooting Guide

Problem

You enqueue a Sidekiq job and it sits in the queue forever. The job never runs, and there’s no error visible in your application logs.

MyWorker.perform_async(user.id)
# Returns a JID, but the job never executes

Symptoms

  • perform_async returns a JID successfully (no exception on enqueue)
  • The Sidekiq dashboard shows jobs in the “Enqueued” or “Busy” queue, stuck
  • sidekiq.log shows no activity for new jobs
  • The worker’s perform method’s puts / Rails.logger statements never appear
  • Job count in Redis (LLEN queue:default) keeps growing

Root Cause

Sidekiq uses Redis as its job store. The common causes for jobs not processing:

  1. Sidekiq process isn’t running — enqueue works (Redis is up) but no worker is consuming
  2. Wrong queue name — the worker listens on default but your job goes to a custom queue
  3. Redis connection issue — the worker can’t reach Redis or has stale configuration
  4. Jobs are in the Retry queue — they failed and Sidekiq’s retry logic is backing off
  5. Concurrency limit — all threads are busy processing long-running jobs

Solution

Step 1: Verify Sidekiq is running

ps aux | grep sidekiq
# Should show one or more Sidekiq processes

If not running:

bundle exec sidekiq
# Or with systemd: sudo systemctl start sidekiq

Step 2: Check the Sidekiq dashboard

Mount the dashboard in routes.rb:

require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'

Visit /sidekiq and check:

  • Queues tab — are jobs piling up?
  • Retries tab — did your jobs fail and move to retry?
  • Busy tab — are workers running but taking too long?
  • Dead tab — did jobs exhaust all retries?

Step 3: Check queue names match

Your worker defines which queue it listens on:

class MyWorker
  include Sidekiq::Worker
  sidekiq_options queue: :critical  # <-- This worker listens on 'critical'
end

But you may be enqueueing to default:

MyWorker.perform_async(id)  # Goes to 'critical' queue (respects sidekiq_options)

Or the Sidekiq process may not be configured to process that queue:

bundle exec sidekiq -q default -q critical
# Must include the queue your worker uses

Step 4: Inspect Redis directly

redis-cli

# List all queues
KEYS queue:*

# Check queue length
LLEN queue:default

# Peek at a job
LRANGE queue:default 0 0

# Check retry set
ZCARD retry

# Check dead set
ZCARD dead

# Flush stuck queues (caution!)
DEL queue:default

Step 5: Check for code loading issues

If you recently renamed a worker or changed its namespace:

# Verify Sidekiq knows about your worker
Sidekiq::WorkerRegistry.new.entries.map(&:klass)
# Should include 'MyWorker'

Restart Sidekiq (it loads classes at boot): bundle exec sidekiq again, or kill -USR1 <pid> for quiet restart.

Verification

# In Rails console, enqueue a test job
class TestWorker
  include Sidekiq::Worker
  def perform(msg)
    Rails.logger.info "TEST: #{msg}"
  end
end

TestWorker.perform_async("hello")

# Watch sidekiq logs for the output
# Watch Sidekiq dashboard — the job should move from Enqueued → Busy → Done

Prevention

  • Use sidekiq.yml to configure queues declaratively
  • Set up Sidekiq monitoring with the web dashboard (protect with auth in production)
  • Add a health check that verifies Sidekiq can enqueue and process a job
  • Log job lifecycle events: use sidekiq_options callbacks (retry, dead) for alerts
  • Set REDIS_URL explicitly in production environments

References


Advertisement