Read more

How to implement simple queue limiting/throttling for Sidekiq

Arne Hartherz
September 24, 2020Software engineer at makandra GmbH

The sidekiq-rate-limiter Show archive.org snapshot gem allows rate-limiting Sidekiq jobs and works like a charm. However, it needs to be integrated on a per-worker basis.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

If you want to limit a whole queue instead, and if your requirements are simple enough, you can do it via a Sidekiq middleware Show archive.org snapshot yourself.

Here is an example that limits concurrency of the "mailers" queue to 1. It uses a database mutex via the with_advisory_lock Show archive.org snapshot gem but you could easily use something else.

class SidekiqMailersThrottle
  def call(worker, job_options, queue)
    if queue == 'mailers'
      ApplicationRecord.with_advisory_lock('mailers-throttle') do
        yield
      end
    else
      yield
    end
  end
end

Sidekiq.configure_server do |config|
  config.server_middleware do |chain|
    chain.add SidekiqMailersThrottle
  end
end

Some hints:

  • Using this approach, workers will be blocked while jobs are waiting for the mutex to free up. The sidekiq-rate-limiter gem re-queues blocked jobs so that other jobs can be worked off in the meantime (which is smart). Depending on your use case, blocking workers might or might not be an issue.
  • To increase concurrency, you might do something as simple as naming your lock "mailers-throttle-#{rand(4)}" (not perfect, but might be good enough).
  • For rate-limiting (e.g. only 1 job per 5 seconds) you could name it "mailers-throttle-#{(Time.now.to_i / 5.0).to_i}".

Also note that Sidekiq allows configuring queue weights Show archive.org snapshot . This is a different approach and will not throttle a queue, but instead allow some queues to be picked up more often than others.
Finally, it might be an option to spawn a separate Sidekiq process to work off only your a specific queue, and limit its worker count.

Posted by Arne Hartherz to makandra dev (2020-09-24 11:07)