Running a high volume Rails app on Heroku for free
In 3 easy steps you can setup a rails app on Heroku that can easily handle 200 requests per second and 100 concurrent connections, for free.
Step 1: Use Unicorn
With the Cedar stack on Heroku, you can now run any process, so why not use Unicorn. Here’s how to set this up.
Add this to your Gemfile
group :production do gem 'unicorn' end
# If you have a very small app you may be able to # increase this, but in general 3 workers seems to # work best worker_processes 3 # Load your app into the master before forking # workers for super-fast worker spawn times preload_app true # Immediately restart any workers that # haven't responded within 30 seconds timeout 30
Add this to your Procfile
web: bundle exec unicorn_rails -p $PORT -c ./config/unicorn.rb
Step 2: Setup New Relic
Why do I need this? Simple, by adding availability monitoring, New Relic will send a request to your app every 30 seconds. This will prevent Heroku from stopping your app during idle periods, and no user should ever see an app spin up delay.
First, setup the New Relic addon. Instructions can be found here
Step 3: Use AWS CloudFront for serving static assets
Ok, I lied, not all steps are free. However, this step is almost too cheap to skip. It reduces the load on your Heroku workers and decreases page load times for your users. There are couple of ways to set this up.
Option 1: Super easy
Use your app as a custom origin server. When creating the CloudFront distribution, use your app’s hostname as the origin domain name. Then in your app set the production asset_host to be the CloudFront distribution URL.
After this is configured, when a user hits your site for the first time, CloudFront will request the necessary assets from your app, cache them, and deliver them to the user. CloudFront will continue to respond with this data, without hitting your app, until it expires. The expiration time is determined by the cache headers returned by your app.
Option 2: Best performance
Have your app upload your assets to an S3 bucket and configure CloudFront to serve the assets from S3. By proactively uploading your assets, CloudFront never hits your app and the assets are already in Amazon’s network for faster retrieval. For automating this process, I recommend asset_sync
Add this to the asset group in your Gemfile
Add this to your initializers config/initializers/asset_sync.rb
if defined?(AssetSync) AssetSync.configure do |config| config.fog_provider = 'AWS' config.fog_directory = 'bucket_name' # These can be found under Access Keys in AWS Security Credentials config.aws_access_key_id = 'REPLACE_ME' config.aws_secret_access_key = 'REPLACE_ME' # Don't delete files from the store config.existing_remote_files = 'keep' # Automatically replace files with their equivalent gzip compressed version config.gzip_compression = true end end
When rake assets:precompile is run, the generated assets will automatically get uploaded to the configured S3 bucket.
By using Unicorn and New Relic you have an app that can serve more requests faster and without delays, and by adding CloudFront we lighten the load on our workers. Now what’s your excuse for not creating the next big thing?