Running Sidekiq On Heroku Free Dyno With Puma
2 min read

Running Sidekiq On Heroku Free Dyno With Puma

Running Sidekiq On Heroku Free Dyno With Puma

In my opinion, Heroku is the nearly perfect place to deploy a project. It provides support for a lot of technologies out of the box with minimal or no configuration.

Similarly, Sidekiq is what I strongly prefer whenever there is a need for background job processing. It ships with all the right set of APIs to deal with background processing and more importantly a great monitoring dashboard.

So, Last weekend I decide to hack on a side-project which has been on my mind forever (I will write about this project in another blog post). I rolled up a new rails project, added Sidekiq with Redis and pieced together a basic functional prototype. When I moved to deployment process I realised - I have to run another dyno to keep the Sidekiq process running.

Now let me be honest with you here, I have an itch for creating side-projects. Once I get hit by a problem I take some time out to hack on it & later I struggle to find time to work on the project again. That's why I don't go with any paid plan in project's infant days.

Coming back to our problem at hand, Heroku already provides a free tier of Redis as an addon – which does

heroku addons:create heroku-redis:hobby-dev

The other half is to figure out how to spawn a Sidekiq process within the same dyno. After some digging I found a great blog post Sidekiq on Heroku with Redis To Go Nano describing how to achieve the same in Unicorn. From here is just a matter of figuring out how to replicate this behaviour in Puma.

...some experiments later...

I got the puma.rb inside config to mimic the same behaviour for me – keeping Heroku Redis' client connection limit in check. Here is the config:

threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }

threads threads_count, threads_count

port        ENV.fetch("PORT") { 3000 }

environment ENV.fetch("RAILS_ENV") { "development" }

workers ENV.fetch("WEB_CONCURRENCY") { 2 }


// Update by (Stefan)
before_fork do 
    @sidekiq_pid ||= spawn('bundle exec sidekiq -t 25')

on_worker_boot do
  ActiveRecord::Base.establish_connection if defined?(ActiveRecord)

on_restart do
  Sidekiq.redis.shutdown { |conn| conn.close }

plugin :tmp_restart

Copy this to your Puma config and deploy this with your Heroku app.

git push heroku master

Be sure to point Procfile to right puma config

bundle exec puma -C config/puma.rb

P.S: I would not recommend this setup at all for your production application. This is strickly for experimental purpose.

Mike Perham (creator of Sidekiq) make some points on Reddit thread which you must checkout before moving ahead with this approach.

I have also updated the code snippet above based the findings (mentioned in the comments below) of Stefan Wrobel.