Sidekiq and Redis in Ruby-on-Rails

Handle background processing and job queuing

Hanwen Zhang
4 min readMay 18, 2024

What is Sidekiq

  • Background job processing in Rails applications, designed to help manage worker processes asynchronously
  • Queue up web requests as a worker process (a worker is a unit that runs concurrent code), and handle a large number of jobs concurrently by using multiple threads.

Why Sidekiq

  • Particularly useful for offloading time-consuming tasks, such as sending emails, processing images, or performing background computations
  • Used to improve the responsiveness, and prevent blocking the main app, it can process multiple jobs concurrently and schedule jobs to run at a later time

Configuration

Create an initializer file for Sidekiq (e.g., config/initializers/sidekiq.rb):

Sidekiq.configure_server do |config|
config.redis = { url: ENV["REDIS_URL"] || "redis://localhost:6379/0" }
end

Sidekiq.configure_client do |config|
config.redis = { url: ENV["REDIS_URL"] || "redis://localhost:6379/0" }
end

Redis

What is Redis

  • Key value pairs that use in-memory for storing data as a database (cache) to give high-performance, single-threaded
  • When you enqueue a job in Sidekiq, Redis is used as the storage backend to manage job queues.

Redis Connection

config.redis - where the connection of sidekiq and redis is happening

$redis = Redis.new(url: ENV["REDIS_URL"] || "redis://localhost:6379/0")

Job Lifecycle

Enqueuing Jobs → Processing Jobs → Retries

Creating a Worker

Create a worker class that defines the background job. Workers are classes that include the Sidekiq::Worker module and a perform method

# app/workers/my_worker.rb
class MyWorker
include Sidekiq::Worker

def perform(*args)
# Perform your background job here
puts "Performing job with arguments: #{args}"
end
end

Sidekiq Job Enqueue

In Sidekiq, jobs are enqueued using the perform_async method, which is part of the Sidekiq API provided in Sidekiq::Worker module

# app/controllers/my_controller.rb
class MyController < ApplicationController
def create
# Enqueue a job
MyWorker.perform_async('arg1', 'arg2')

render plain: "Job has been enqueued"
end
end

For example, we call the cron controller to perform_sync the worker, then introduce a worker with a cronjob to pull data from an external API and store it in our database.

Sidekiq Job Process

Retrieve jobs from the Redis queue, and execute the perform method in the worker class

Sidekiq Job Retries

Sidekiq has built-in support for handling job failures and automatic retries. By default, Sidekiq will automatically retry a failed job.

There is an option for how many times you can retry, where you can customize retries by using sidekiq_options, searching “sidekiq_options retry

Running Sidekiq

Sidekiq API provides access to real-time information about workers, queues, and jobs. The API allows you to perform actions like clearing queues, deleting specific jobs, and retrieving job details.

bundle exec sidekiq is a command used to start the Sidekiq background job processing system in a Ruby on Rails application. Sidekiq is a popular gem for handling background jobs in Ruby applications.

# Access Local Dashboard
# config/routes.rb
http://localhost:{port}/sidekiq
http://localhost:{port}/sidekiq/queues

More Information

Sidekiq

Sidekiq and Active Job both are related to background job processing in Rails applications, both are designed to be processed asynchronously. This is particularly useful for offloading time-consuming tasks, such as sending emails, processing images, or performing background computations, to improve the responsiveness of web applications and prevent them from blocking the main application.

Sidekiq is a Ruby library that helps manage worker processes in Rails applications.

Active Job is a framework for declaring jobs and making them run on a variety of queuing backends.

Redis

Currently, Sidekiq pro has a mechanism to reduce whenever Redis is down, it will save lost jobs in RAM that allows storing the last 1000 pushing jobs on local memory in case the connection between the Sidekiq client and Redis server is lost.

In case Redis is down, when the Sidekiq client adds a job, the job will be added to a client queue. After Redis is back, when the Sidekiq client adds a new job, it also adds all jobs in the client queue to Redis. This avoids job loss. Extended pushing jobs will be lost if there are more than 1000 pushing jobs.

To know if a job is unique or not, Sidekiq-unique-job needs to check the Redis queue. When Redis is down, the sidekiq-unique-job throws exceptions. However, if the Redis is down, unique jobs will be lost.

The Schedule Queue on Sidekiq is based on a nonrelational database (redis) which has to look through the whole list to find what to run (which is the issue moving everything to a cronjob would be solving for scalability). So, storing the execution time in a relational database where a filtering select statement shouldn’t take long.

Overall, redis uses memory for storing data to give high performance. As long as the memory is big enough, we will perform well.

Recap

  • A job is a unit of work in your Ruby application
  • A queue is a list of jobs that are ready to execute right now
  • A process is a Sidekiq process with one or more threads for executing jobs.
  • Queue is one part of Sidekiq “processes” that are running
  • Queue up web requests as a worker process

--

--

Hanwen Zhang

Full-Stack Software Engineer at a Healthcare Tech Company | Document My Coding Journey | Improve My Knowledge | Share Coding Concepts in a Simple Way