Sidekiq is one of the most popular open-source background job libraries for Ruby. As one of ActiveJob's most popular backends, it's often used to run asynchronous jobs in Rails applications.

It leans on Redis to manage queues and jobs, which makes it fast. Developers can run background jobs using Sidekiq with or without ActiveJob, and we'll explore both in this article.

Just as useful - Sidekiq scheduled jobs allow you to run a job after a given amount of time or at a given time. In this article, we will explore defining a background job, performing background jobs after a given time period as well performing them at a given time. You'll learn to do each of these scheduling methods both with ActiveJob and without it.

Sidekiq scheduled jobs without ActiveJob

Using Sidekiq to write a Ruby background job with or without ActiveJob is very similar, but enqueuing the jobs is a bit different. In this section, we'll write a Ruby class that inherits from Sidekiq. Then, we'll explore a few ways to enqueue this job.

We won't explore Sidekiq Pro or Sidekiq Enterprise, but they offer advanced background jobs features including expiring unprocessed background jobs, job metric reporting, and even rate limiting.

First, you'll need to install the Sidekiq gem. Run:

gem install sidekiq

Sidekiq relies on Redis, so you'll need to install that.

brew install redis

Writing Sidekiq background jobs

Finally, we'll write a small Sidekiq job. In a new file called hello_job.rb, paste the following:

require 'sidekiq'

class HelloJob
  include Sidekiq::Job

  def perform
    puts "Hello from inside a background job!"
  end
end

puts "hello from outside the job"

HelloJob.perform_async

puts "hello from after the job"

This class is a simple background job that prints out the message, Hello from inside a background job!". For this example, we print that text from outside the job, perform the job asynchronously, and print some text after that method call to indicate the order of execution.

Process background jobs with just Sidekiq

Because this job doesn't need ActiveJob, we can run it with only Redis.

Start Redis in the background using Homebrew:

brew services start redis

Then, run the background job with:

sidekiq -r ./hello_job.rb

The execution of the job is asynchronous, so it may execute before or after the "hello from after the job" text is printed to the console. In my case, the job executes after this text is printed.

A screenshot of the Sidekiq job executing in a terminal Execution of the Sidekiq background jobs

Now, you can kill the sidekiq processes with CTRL + c.

Scheduling a Sidekiq job with perform_in

Our first example defines the Sidekiq job and enqueues it in the same file. That enqueue method, perform_async, runs the job in the background as soon as it can.

If you want to delay execution by an amount of time, enqueue the job with perform_in instead. We'll change the earliest example to do this, scheduling the job for 1 minute from enqueue.

require 'sidekiq'

class HelloJob
  include Sidekiq::Job

  def perform
    puts "Hello from inside a background job!"
  end
end

puts "hello from outside the job"

HelloJob.perform_in(60)

puts "hello from after the job"

You can run this job by starting a Sidekiq worker with:

sidekiq -r ./hello_job.rb

Scheduling a Sidekiq job with perform_at

If you know when your job should execute, you should use the perform_at method to enqueue it for a given time. The original example, when using this method, looks like this:

require 'sidekiq'

class HelloJob
  include Sidekiq::Job

  def perform
    puts "Hello from inside a background job!"
  end
end

puts "hello from outside the job"

HelloJob.perform_at(Time.now+60)

puts "hello from after the job"

Using Sidekiq with ActiveJob for Rails background jobs

ActiveJob exists to make it easy to create and run background jobs in Rails with an abstract backend. Sidekiq is a popular backend for managing these jobs, but changing to another option like Solid Queue is trivial thanks to this abstraction.

You can use Sidekiq for Rails scheduled jobs without ActiveJob, but we'll focus on using ActiveJob.

Setting up the Rails application

If you don't already have a Rails project, create one:

rails _7.1.1_ new background-job-example-app

Then, cd into the newly created directory

cd background-job-example-app

Writing a background job with ActiveJob

Next, use a Rails generator to create a new job file:

rails generate job hello_world

This will create a new app/jobs/hello_world_job.rb file, in which you should paste the following code:

class HelloWorldJob < ApplicationJob
  queue_as :default

  def perform(*args)
    puts "Hello from inside a background job!"
  end
end

Configuring ActiveJob and Sidekiq

Next, we'll set up ActiveJob to use Sidekiq. In config/application.rb, set the queue adapter:

config.active_job.queue_adapter = :sidekiq

Finally, add the Sidekiq Gem to the Gemfile by running:

bundle add sidekiq

Configuring the Sidekiq UI

Sidekiq ships with the Sidekiq dashboard, which makes it easy to monitor job execution, you just have to mount it in config/routes.rb file:

require 'sidekiq/web'
# or require 'sidekiq/pro/web'
# or require 'sidekiq-ent/web'

Myapp::Application.routes.draw do
  mount Sidekiq::Web => "/sidekiq" # mount Sidekiq::Web in your Rails app
  ...
end

Running the background job with perform_later

If you haven't already, start Redis in the background using Homebrew:

brew services start redis

Start your Rails app by running rails server and visit the Sidekiq UI at localhost:3000/sidekiq

In a separate terminal window, open a Rails console with rails c and enqueue the new job with perform_later:

HelloWorldJob.perform_later

Looking at the Sidekiq UI, you can see the number of jobs you've enqueued, completed jobs, and failed jobs. This is particularly helpful when debugging failed jobs or remediating an incident in a production environment.

A screenshot of the Sidekiq UI showing a job successfully executed The Sidekiq UI with one job executed and one enqueued

This example only demonstrated asynchronous job execution, not scheduled jobs. Enqueueing a job can be combined with a set method call to schedule a job for a time or amount of time in the future.

Running an ActiveJob job at a future time

Rather than calling HelloWorldJob.perform_later in the Rails console, we can chain a set method call to perform the job at some future time. To perform this job tomorrow night, run this in the Rails console:

HelloWorldJob.set(wait_until: Date.tomorrow.at_end_of_day).perform_later

This schedules the job for the DateTime of just before midnight the day after it's run. We don't have to wait for the job to execute to see that it was scheduled without errors. The Sidekiq UI shows that the job is properly scheduled and waiting for its execution time.

The Sidekiq scheduled jobs UI The Sidekiq scheduled jobs UI showing 1 scheduled job

Running an ActiveJob job after some time

Scheduling a job with ActiveJob to run some time in the future relative to the current time is a similar process. In the Rails console, run:

HelloWorldJob.set(wait_until: 2.minutes).perform_later

This schedules the job for the time 2 minutes from the current time, and can be validated with the Sidekiq UI.

Monitoring Sidekiq with Honeybadger

Our Ruby gem monitors Sidekiq errors automatically, so all you need to do is install it). You can also monitor Sidekiq metrics with Honeybadger Insights if you use bundle exec honeybadger install API_KEY --insights when installing the gem.

Honeybadger automatically monitors Sidekiq errors, giving you visibility into your background jobs. First, install the Honeybadger gem by adding it to your Gemfile:

gem 'honeybadger'

Next, run:

bundle install

Finally, set up the gem with your API key:

bundle exec honeybadger install <Your project API key>

You can also use Honeybadger Insights to monitor Sidekiq metrics directly. If you're installing the Gem for the first time, you can use this install command:

bundle exec honeybadger install API_KEY --insights

Leveraging Sidekiq for delayed jobs in Rails

Sidekiq is a powerful tool for handling background jobs in Ruby and Rails applications. Whether you choose to use it standalone or integrate it with ActiveJob, Sidekiq offers robust capabilities for asynchronous job processing and scheduling.

By learning how to write Sidekiq scheduled jobs, you can optimize your application's performance and improve user experience by offloading time-consuming operations to the background. Whether you're building a small application or building Ruby on Rails background jobs with Sidekiq, understanding Sidekiq is a crucial skill for any Ruby or Rails developer.

If you want to take advantage of Honeybadger's monitoring, whether for Sidekiq errors or metrics, sign up for a free trial today!

author photo
Jeffery Morhous

Jeff is a Software Engineer working in healthcare technology using Ruby on Rails, React, and plenty more tools. He loves making things that make life more interesting and learning as much he can on the way. In his spare time, he loves to play guitar, hike, and tinker with cars.

More articles by Jeffery Morhous