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_asyncreturns a JID successfully (no exception on enqueue)- The Sidekiq dashboard shows jobs in the “Enqueued” or “Busy” queue, stuck
sidekiq.logshows no activity for new jobs- The worker’s
performmethod’sputs/Rails.loggerstatements 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:
- Sidekiq process isn’t running — enqueue works (Redis is up) but no worker is consuming
- Wrong queue name — the worker listens on
defaultbut your job goes to a custom queue - Redis connection issue — the worker can’t reach Redis or has stale configuration
- Jobs are in the Retry queue — they failed and Sidekiq’s retry logic is backing off
- 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.ymlto 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_optionscallbacks (retry,dead) for alerts - Set
REDIS_URLexplicitly in production environments
References
Advertisement