Adding Concurrency to Rails Apps with Unicorn

With support for Node.js, Java, Scala and other multi-threaded languages, Heroku allows you to take full advantage of concurrent request processing and get more performance out of each dyno. Ruby should be no exception.

If you are running Ruby on Rails with Thin, or another single-threaded server, you may be seeing bottlenecks in your application. These servers only process one request at a time and can cause unnecessary queuing. Instead, you can improve performance by choosing a concurrent server such as Unicorn which will make your app faster and make better use of your system resources. In this article we will explore how Unicorn works, how it gives you more processing power, and how to run it on Heroku.

Concurrency and Forking

At the core of Heroku is the Unix Philosophy, and we see this philosphy at work in Unicorn. Unicorn uses the Unix concept of forking to give you more concurrency.

Process forking is a critical component of Unix's design. When a process forks it creates a copy of itself. Unicorn forks multiple OS processes within each dyno to allow a Rails app to support multiple concurrent requests without requiring them to be thread-safe. This means that even if your app is only designed to handle one request at a time, with Unicorn you can handle concurrent connections.

Unicorn leverages the operating system to do most of the heavy lifting when creating and maintaining these forks. Unix-based systems are extremely efficient at forking, and even take advantage of Copy on Write optimizations that are similar to those in the recently released Ruby 2.0.

Unicorn on Rails

By running Unicorn in production, you can significantly increase throughput per dyno and avoid or reduce queuing when your app is under load. Unicorn can be difficult to setup and configure, so we’ve provided configuration documentation to make it easier to get started.

Let's set up a Rails app to use Unicorn.

Setting up Unicorn

First, add Unicorn to your application Gemfile:

gem 'unicorn'

Run $ bundle install, now you are ready to configure your app to use Unicorn.

Create a configuration file for Unicorn at config/unicorn.rb:

$ touch config/unicorn.rb

Now we're going to add Unicorn-specific configuration options, that we explain in detail in Heroku's Unicorn documentation:

# config/unicorn.rb
worker_processes 3
timeout 30
preload_app true

before_fork do |server, worker|

  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT',

  defined?(ActiveRecord::Base) and

after_fork do |server, worker|

  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT'

  defined?(ActiveRecord::Base) and

This default configuration assumes a standard Rails app with Active Record, see Heroku's Unicorn documentation for more information. You should also get acquainted with the different options in the official Unicorn documentation.

Now that we've got your app setup to use Unicorn, you’ll need to tell Heroku how to run it in production.

Unicorn in your Procfile

Change the web command in your Procfile to:

web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb

Now try running your server locally with $ foreman start. Once you're happy with your changes, commit to git, deploy to staging, and when you're ready deploy to production.

A World of Concurrency

With the recent release of the Rails 4 beta, which is threadsafe by default, it's becoming increasingly clear that Rubyists care about concurrency.

Unicorn gives us the ability to take multiple requests at a time, but it is by no means the only option when it comes to concurrent Rack servers. Another popular alternative is Puma which uses threads instead of forking processes. Puma does however require that your code is threadsafe.

If you've never run a concurrent server in production, we encourage you to spend some time exploring the ecosystem. After all no one knows your app's requirements better than you.

Whatever you do don't settle for one request at a time. Demand performance, demand concurrency, and try Unicorn today.

Run JRuby on Heroku Right Now

Over a year ago Heroku launched the Cedar stack and the ability to run Java on our platform. Java is known as a powerful language - capable of performing at large scale. Much of this potential comes from the JVM that Java runs on. The JVM is the stable, optimized, cross-platform virtual machine that also powers other languages including Scala and Clojure. Starting today you can leverage the power of the JVM in your Ruby applications without learning a new language, by using JRuby on Heroku.

After a beta process with several large production applications, we are pleased to move JRuby support into general availability immediately. One of these companies Travis CI which provides free CI testing to open source repositories, and a pro plan for private projects, was a JRuby beta tester. Josh Kalderimis of the Travis team had this to say about using JRuby on Heroku:

We love JRuby, everything from the threading support to having the power of the JVM at our finger tips. But what we love most is that we can set up a JRuby app in seconds, the same way as all of our other Heroku apps. Git push and it's live, no matter what the language.

We've been working with the JRuby team to make sure that the experience using the language on Heroku is going to be everything you've come to expect from using our platform. So why should you be interested in running JRuby?

Why JRuby

If you're coming from a Java background and want to use a more dynamic language, JRuby allows you to leverage the syntax of Ruby with the the ability to run JVM based libraries. If you're a Ruby developer already on Heroku, the JRuby implementation has several unique features that you can leverage. The most prevalent difference between running code on JRuby and MRI, or cRuby, is JRuby's lack of a Global Virtual Machine Lock. This means you can run multiple threads of JRuby code within the same process. While cRuby does allow you to perform IO and other non-ruby commands in parallel threads, running Ruby code concurrently can only be done in multiple processes. The second difference is the JVM ecosystem. JRuby can use Java libraries such as JDBC based database drivers. Many of these libraries have been heavily optimized and can offer speed upgrades.

JRuby on Heroku

JRuby on Heroku lowers the barrier of entry to both learning and running a new language in production. The interface of JRuby with the Heroku platform is the same as our other languages: you push your code to us and we do the rest. You don't need to think about all of the details of running a new language. The result is you get to focus on adding features, not on your how to deploy and keep your systems up.

We have been working with the JRuby community together to make sure the experience is a good one. Charles Nutter, the co-lead of JRuby, is excited about the future of running JRuby on Heroku:

One of the most frequently-requested features for JRuby isn't a JRuby feature at's support for JRuby on Heroku. We're very excited that Heroku now officially supports JRuby, and we're looking forward to working with and supporting Heroku users trying out JRuby on their cloud of choice.

By normalizing the interface to deployment across implementations, we hope to ease the process of trying new intrepreters within the Ruby community. We are excited to see a new class of applications, by running Ruby on the JVM, deployed and supported on Heroku. With all these options, which Ruby should you use in production?

Which Ruby to Use?

Heroku supports many languages, and we have a long and happy history of supporting Ruby. We are continuing to invest in the exciting future of MRI we are also excited about the ability for you to run your code on the interpreter of your choice. This can open up new possibilities such as taking advantage of different VM optimizations or concurrent Ruby processing.

As you're trying JRuby, remember that it may behave slightly differently than you're used to with MRI. If you're interested in trying JRuby out on an existing Heroku app, you can read more about converting an existing Rails app to use JRuby.

Every app is different and every project has different requirements. Having the ability to quickly and easily run your app in production on multiple Ruby VMs gives you the power to choose.

Try it Today

If you have an existing Rails app you can deploy your existing app on JRuby. If you're just starting from scratch, running JRuby on Heroku is a breeze. All you need to do is specify the version of Ruby you want to run, the engine, and the engine version in your Gemfile:

ruby '1.9.3', engine: 'jruby', engine_version: '1.7.1'

You'll need to run bundle install with JRuby locally, then commit the results and push to Heroku:

$ git add .
$ git commit -m "trying JRuby on Heroku"
$ git push heroku master
Counting objects: 692, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (662/662), done.
Writing objects: 100% (692/692), 141.01 KiB, done.
Total 692 (delta 379), reused 0 (delta 0)

-----> Heroku receiving push
-----> Ruby/Rails app detected
-----> Using Ruby version: ruby-1.9.3-jruby-1.7.1
-----> Installing JVM: openjdk7-latest
-----> Installing dependencies using Bundler version 1.2.1
# ...

That should be all you need to do to run JRuby on Heroku. If you're converting an existing Rails application, please read moving an existing Rails app to run on JRuby.

While you're trying JRuby out on Heroku you can also try out Ruby 2.0.0 preview, before it is released in February.


With the release of JRuby on Heroku now you can to run your code on multiple VMs, and leverage concurrent Ruby code in production. You've got a standard interface to deployments and the power to choose the right tool for the right job. Special thanks to all of the customers who tried the JRuby beta, and to the JRuby team for being available for technical support. Give JRuby a try and let us know what you think.

Hacking mruby onto Heroku

If you're in the Ruby world, you've likely heard about mruby, Matz's latest experimental Ruby implementation. What I bet you didn't know is that you can run mruby on Heroku right now. As a matter of fact you can run just anything on Heroku, as long as it can compile it into a binary on a Linux box.

If you're new to mruby, or to compiling binaries take a look at my last article Try mruby Today. I cover getting mruby up and running on your local machine. If you are already up to speed then follow along as we use vulcan to package mruby as binary, wrap it up in a custom buildpack and then launch an app to use mruby on the Heroku cloud.

Continue Reading ...


If you missed it yesterday we announced official support for Ruby 2.0.0 Preview1, and announced the dates for our developer conference, Waza 2013, including the Waza call for Speakers.

Ruby 2.0 Preview Available on Heroku

When Heroku first launched you could only use one version of Ruby: 1.8.6. As the Ruby implementation matured and improved, so did Heroku. We recently announced the ability to specify your ruby version on Heroku, and we are happy to announce the first preview-build of Ruby available: starting today you can use Ruby 2.0 preview1 on Heroku.

Ruby 2.0

The Ruby core team has been hard at work on Ruby 2.0, which has a host of new features and boasts performance improvements. You can get a list of the major new features on the official Ruby 2.0.0 Preview1 announcement.

Heroku has been committed to the Ruby project by sponsoring the work of Yukihiro "Matz" Matsumoto, Koichi Sasada and Nobuyoshi Nakada on MRI Ruby. We have been very pleased with Ruby Core's progress, and look forward to the full release. You can take an in-depth look at the new Ruby 2.0 features available. But don't just read about it, try it out on Heroku today:

Get Ruby 2.0 Running on Heroku

Start by making a Gemfile that specifies Ruby 2.0.0:

$ echo 'source ""'  > Gemfile
$ bundle install
$ echo 'ruby "2.0.0"' >> Gemfile

Add the files to a Git repository:

$ git init
$ git add .
$ git commit -m "Ruby 2.0.0 preview on Heroku"

Then create a new heroku app and deploy:

$ heroku create
$ git push heroku master
-----> Heroku receiving push
-----> Ruby app detected
-----> Using Ruby version: ruby-2.0.0
-----> Installing dependencies using Bundler version 1.2.1
       Running: bundle install --without development:test --path vendor/bundle --binstubs bin/ --deployment
       The Gemfile specifies no dependencies
       Your bundle is complete! It was installed into ./vendor/bundle
       Cleaning up the bundler cache.
-----> Discovering process types
       Procfile declares types -> (none)
       Default types for Ruby  -> console, rake
-----> Compiled slug size: 23.3MB
-----> Launching... done, v4 deployed to Heroku

 * [new branch]      master -> master

Now you can run Ruby 2.0 beta on Heroku!

$ heroku run bash
Running `bash` attached to terminal... up, run.1
~ $ ruby --version
ruby 2.0.0dev (2012-11-01 trunk 37411) [x86_64-linux]
~ $ ruby -e "puts 'hello world'"
hello world

Why Run 2.0 Preview1?

Ruby 2.0 will ship on February 24th, 2013 - which is four days before our developer conference Waza. Heroku's own Matz has announced that Rails 3.2 apps should work with Ruby 2.0 if they work on Ruby 1.9. Help us find any incompatibilities by checking your existing applications on Heroku. If you run into any bugs in the Ruby implementation, please open a bug in the Ruby bug tracker and let the Ruby team know what didn't work with the implementation.


If you are updating an existing app you will likely need to update your config vars manually. New apps should not experience any problems.


Thanks to the entire Ruby Core Team for their hard work on this release of Ruby, and special thanks to Terence Lee. Terence is Heroku's Ruby buildpack maintainer who did the leg work to enable Ruby 2.0.0 Preview1 on Heroku. Please try out this Ruby preview today, to help the Ruby core team and to help our community. Try it today.

Multiple Ruby Version Support on Heroku

Maximizing parity between development and production environments is a best practice for minimizing surprises at deployment time. The version of language VM you're using is no exception. One approach to this is to specify it using the same dependency management tool used to specify the versions of libraries your app uses. Clojure uses this technique with Leinigen, Scala with SBT, and Node.js with NPM. In each case, Heroku reads the dependency file during slug compile and uses the version of the language that you specify.

Today, we're pleased to announce that we've added support for specifying a Ruby version to Gem Bundler, the dependency management tool for Ruby. This will allow you to specify a version of Ruby to be used in your Ruby app on Heroku.

Try it out:

$ gem install bundler --pre

In your Gemfile:

source ''

ruby '1.9.3'
gem  'rails', '3.2.3'


$ bundle install
$ git add Gemfile
$ git commit -m 'use Ruby 1.9.3'
$ git push heroku master

Prove that you're running 1.9.3:

$ heroku run 'ruby -v'
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]

$ heroku run 'ruby -e "puts RUBY_VERSION"'

Patch Versions

While you can specify the version of Ruby for you app, you can't specify a patch version, such as Ruby 1.9.2-p290. Ruby patches often include important bug and security fixes and are extremely compatible. Heroku will provide the most secure patch level of whatever minor version number you request.


Thanks to Terence Lee Heroku Ruby team member and bundler maintainer for the additional support of ruby versions to the Heroku Ruby Buildpack and orchestrated the release of Bundler 1.2.0. Also thanks to Yehuda Katz and the entire Bundler team for helping get this release out the door.

Browse the blog archives, subscribe to the full-text feed, or visit the engineering blog.