I have been spending the last week tuning up an application we support at work. It really is a massive piling of steaming dung in places too.
Anyway after getting through a whole bunch of other performance issues, I turned my attention to setting up a Content Delivery Network(CDN). You see on Heroku hosting you only get as many front ends as you want to pay for. While you might think these work like passenger processes hosting up dynamic content, you would only be partly correct. The Heroku web dyno not only serves up Rails content, but also all the static content. This means if you page has a bunch of images, a css file and some javascript, you are loading up that dyno pretty heavily.
Enter the CDN. With a CDN you put all your content on a separate host. In this case I used Amazons CDN platform called CloudFront. Since we were already using S3 storage for attachments, something that is a must on Heroku anyway, setting up CloudFront was pretty easy. You go into the CloudFront configuration and setup a new distribution. In setting up the distribution the only thing you really need to set is the Origin. With Heroku and Rails 3.1, you want to set the origin to the URL of your website. CloudFront will pull files from there on demand as they are requested and cache them in it’s system.
Back to your Rails 3.1 distribution. All that is needed is the following line in your Rails 3.1 production.rb environment file:
config.action_controller.asset_host = "xxxxxxxxx.cloudfront.net"
Just put in your CloudFront distributioni URL and deploy. If you have already setup your Assets management, everything else just works.
Because Rails 3.1 generates unique filenames for each change in the files, you don’t have to worry about files going stale on the CDN, and with the Origin pointing back to your site, you don’t even have to upload the files there.
The performance improvement I saw was astounding. Besides needing less web dynos for performance, the amazon CDN is also better at scaling requests up. I saw numbers as high as 350 requests per second with concurrency of 100 with little delay at that level.