Sending email, generating PDFs, resizing images or calling webhooks inside a web request makes pages slow and fragile. Sidekiq moves that work into background jobs that run in separate worker processes. This guide sets it up on your own Linux VPS.
Sidekiq runs Ruby background jobs using Redis as the queue. It needs a long-running worker process and a Redis server, so it belongs on a VPS, not shared hosting. This guide covers installing Redis, configuring Sidekiq with Active Job, systemd services, monitoring and scaling.
Why Sidekiq (not Solid Queue, DelayedJob, Resque)?
Rails 8 ships with Solid Queue, a database-backed queue that needs no Redis and suits many apps. Sidekiq remains the common choice when job volume is high or you already run Redis:
| Queue | Backend | Throughput | Best for |
|---|---|---|---|
| Solid Queue | Database (PostgreSQL, MySQL, SQLite) | Moderate; limited by the database | Rails 8 default, apps without Redis |
| Sidekiq | Redis (or a compatible server such as Valkey) | High; multi-threaded workers | High job volume, existing Redis |
| DelayedJob | Database | Lower | Legacy apps |
| Resque | Redis | Moderate; one process per job | Older apps, less active |
Sidekiq's threads and in-memory Redis queue let one process handle far more jobs than a database-backed queue. Benchmark with your own jobs before deciding: many apps are fine on Solid Queue.
Architecture on a VPS
[Rails web (Puma)] ──► enqueues job ──► [Redis]
│
[Sidekiq worker 1] ◄──── picks jobs ─────┤
[Sidekiq worker 2] ◄──── picks jobs ─────┘- Rails web process (Puma) accepts HTTP, enqueues jobs
- Redis holds the queue
- Sidekiq worker processes pull jobs, run them
- All three run as systemd services on the same VPS (or different VPS for scale)
Step 1 — Install Redis
On the VPS:
# AlmaLinux 9 (on AlmaLinux 10 the packaged equivalent is Valkey: dnf install valkey)
sudo dnf install -y redis
sudo systemctl enable --now redis
# Ubuntu
sudo apt install -y redis-server
sudo systemctl enable --now redis-server
redis-cli ping # → PONGEnable persistence so queued jobs survive a server restart (the config file is /etc/redis/redis.conf on both AlmaLinux 9 and Ubuntu; the service is redis on AlmaLinux and redis-server on Ubuntu):
sudo sed -i 's/^appendonly no/appendonly yes/' /etc/redis/redis.conf
sudo systemctl restart redis # or: redis-serverKeep Redis bound to 127.0.0.1 (the default) and never open port 6379 to the internet. If other servers must reach it, see the scaling section below.
Step 2 — Add Sidekiq to your Rails app
Gemfile:
gem 'sidekiq', '~> 8.0' # use the current major version; check its Ruby and Redis requirementsbundle installconfig/initializers/sidekiq.rb:
Sidekiq.configure_server do |config|
config.redis = { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0') }
end
Sidekiq.configure_client do |config|
config.redis = { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379/0') }
endconfig/application.rb:
config.active_job.queue_adapter = :sidekiqStep 3 — Write a job
app/jobs/send_welcome_email_job.rb:
class SendWelcomeEmailJob < ApplicationJob
queue_as :default
retry_on Net::OpenTimeout, Net::ReadTimeout, wait: :polynomially_longer, attempts: 5
def perform(user_id)
user = User.find(user_id)
UserMailer.welcome(user).deliver_now
end
endEnqueue:
SendWelcomeEmailJob.perform_later(user.id)Step 4 — Systemd service for Sidekiq
/etc/systemd/system/sidekiq-yourapp.service:
[Unit]
Description=Sidekiq for YourApp
After=network.target redis.service postgresql.service
[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/home/deploy/rails_app
Environment="RAILS_ENV=production"
Environment="PATH=/home/deploy/.rbenv/shims:/usr/bin:/bin"
ExecStart=/home/deploy/.rbenv/shims/bundle exec sidekiq -e production -C /home/deploy/rails_app/config/sidekiq.yml
ExecReload=/bin/kill -TSTP $MAINPID
Restart=on-failure
RestartSec=5
# Graceful shutdown — let Sidekiq finish current jobs
TimeoutStopSec=30
KillSignal=SIGTERM
EnvironmentFile=-/home/deploy/rails_app/.env
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.targetconfig/sidekiq.yml:
:concurrency: 10 # threads per worker process
:queues:
- [critical, 3] # weight 3 — critical queue serviced 3× more
- [default, 2]
- [mailers, 1]
- [low, 1]
:timeout: 25 # jobs killed after 25s if still running when SIGTERMEnable:
sudo systemctl daemon-reload
sudo systemctl enable --now sidekiq-yourapp
sudo journalctl -u sidekiq-yourapp -fStep 5 — Sidekiq web UI
Mount the dashboard for monitoring:
config/routes.rb:
require 'sidekiq/web'
Rails.application.routes.draw do
authenticate :user, ->(u) { u.admin? } do
mount Sidekiq::Web => '/sidekiq'
end
# ... other routes
endThe authenticate block comes from Devise; use your own admin check if you don't use Devise, and never mount the dashboard without authentication. Visit https://yourcompany.com/sidekiq to see queued, retrying, scheduled and dead jobs.
Job patterns
Scheduled / delayed jobs
ReminderJob.set(wait: 1.hour).perform_later(booking_id)
ReminderJob.set(wait_until: 2.days.from_now).perform_later(booking_id)Recurring jobs (Sidekiq-cron or whenever gem)
# Gemfile
gem 'sidekiq-cron'
# config/schedule.yml (recent sidekiq-cron versions load this file
# automatically; older ones need an initializer, see its README)
cleanup_old_sessions:
cron: "0 2 * * *" # 2 AM daily
class: "CleanupOldSessionsJob"
reindex_search:
cron: "0 */6 * * *" # every 6 hours
class: "ReindexSearchJob"Unique jobs (prevent duplicates)
# Gemfile
gem 'sidekiq-unique-jobs'
# sidekiq-unique-jobs works with native Sidekiq jobs, not Active Job.
# Check that its version supports your Sidekiq version.
class ImportantJob
include Sidekiq::Job
sidekiq_options lock: :until_executed
def perform(id)
# Only one queued/running job per id
end
endScaling patterns
Single VPS, multiple workers:
Add more worker processes on the same VPS — 2–4 is typical before RAM becomes the limit.
/etc/systemd/system/[email protected] (templated service)Start [email protected], @2.service etc.
Multi-VPS (horizontal scale):
Put Redis on a dedicated VPS and point all web and worker servers at it. Protect it with a password (Redis ACL) and either TLS or an encrypted tunnel such as WireGuard, and allow port 6379 only from your own servers:
REDIS_URL=rediss://:[email protected]:6379/0For HA Redis: Sentinel (free) or Redis Cloud (managed).
Monitoring and alerts
Sidekiq stats endpoint:
Sidekiq::Stats.new.enqueued # waiting to run
Sidekiq::Stats.new.retry_size # failed, waiting retry
Sidekiq::DeadSet.new.size # permanently failedExpose as /health/sidekiq and alert when queue >1000 or dead >10.
Sidekiq Pro/Enterprise (commercial):
- Batches (run many jobs, callback when all done)
- Rate limiting
- Reliable fetch, unique jobs, encryption and more
See sidekiq.org for the current features and pricing of each edition. Worth considering if Sidekiq is mission-critical.
Common pitfalls
retry_on and discard_on deliberately and alert on the Retries and Dead counts.MALLOC_ARENA_MAX=2 or use jemalloc, and restart workers on a schedule if needed.maxmemory alert.after_commit callback.Running this on Domain India
- VPS: a Domain India VPS is a self-managed KVM server with full root access, so Rails, Sidekiq, Redis and PostgreSQL can all run on it as systemd services. You install and update them yourself. No backups or snapshots are included with a VPS, so back up your database and Redis data elsewhere.
- Shared hosting: cPanel, DirectAdmin and Webuzo hosting stop long-running processes such as Sidekiq workers, and Redis is not available on any shared plan. Cron jobs on shared hosting run at most every 4 minutes.
- App Platform: there is no Redis add-on, so plan Sidekiq for a VPS.
FAQ
Sidekiq or Solid Queue for a new Rails 8 app?
Start with Solid Queue if your job volume is modest: it is the Rails 8 default and needs no Redis. Choose Sidekiq if you expect high job volume, already run Redis, or need its ecosystem of add-ons.
Can I run Sidekiq on shared hosting?
No. Sidekiq needs a long-running worker process and a Redis server. Domain India shared hosting stops long-running background processes and has no Redis, so run Sidekiq on a VPS.
How many workers on a 2 GB VPS?
Depends on your jobs. Typical Rails worker uses 200–400 MB RAM. 1 web + 1 Sidekiq process (10 threads) fits comfortably. For heavier jobs (PDF, image), 2 worker processes max on 2 GB.
What about Sidekiq + Heroku/Render?
It works the same way there, but you usually pay for each worker and for managed Redis separately. On a self-managed VPS the web app, workers and Redis share one fixed monthly price, in exchange for doing the server administration yourself.
Is Sidekiq safe for critical jobs (payments)?
Yes, with care. Set retry_on for transient errors, use idempotency keys (check "already processed" before calling the payment API), and consider Sidekiq Pro's reliable fetch so jobs are not lost if a worker crashes.
Ready to run background jobs? Compare VPS plans, or open a support ticket if you have questions.
Self-managed KVM VPS with full root access and NVMe storage, from ₹553 a month excluding GST.
See VPS plans