Using Amazon CloudFront CDN

Last Updated: 31 March 2014

Table of Contents

Web usability isn’t just about the User Interface: a large component of usability is speed. On the web, that translates to page load time performance. While focusing on your application code is important, there are many quick win improvements that can be made to the User Interface to dramatically speed up page loads.

Using a Content Delivery Network (CDN) optimises the delivery of static assets on your site. This allows us to offload all requests for these static assets off of your web dynos, which in turn will free those dynos to handle more requests for dynamic content.

Amazon S3

Many developers make use of Amazon’s S3 service for serving static assets that have been uploaded previously, either manually or by some form of build process. Whilst this works, this is not recommended as S3 was designed as a file storage service and not for optimal delivery of files under load. Therefore, serving static assets from S3 is not recommended.

Amazon Cloudfront

Amazon’s CloudFront service is designed as a content delivery network to serve static assets such as CSS or JavaScript files from edge cache locations.

Edge cache locations are groups of servers distributed around the world optimised for the high throughput serving of small static files. Using latency based DNS resolution, Amazon are able to route requests to particular assets to the closest edge cache location to the end user reducing latency, and improving speed.

CloudFront works from what is called a distribution. A distribution is the direct equivalent of an S3 bucket. Each distribution is assigned a domain name that is used to access your distributions assets.

An example distribution URL is d3vam04na8c92l.cloudfront.net.

Note that by using a DNS CNAME record, we can hide this domain behind something from our application e.g. cdn.mydomain.com.

A distribution draws its contents from an origin. The origin is where CloudFront will draw files from should it not have a copy within the distribution. Once a file has been requested from the origin CloudFront will cache that asset and return it directly to the end user.

CDN Operation

Creating a distribution

If you wish to avoid provisioning AWS resources yourself, you can utilize a CDN add-on instead, which will streamline the process and consolidate billing.

To create a CloudFront distribution you will need an Amazon AWS account. Once logged in you can go to the CloudFront control panel and select ‘Create distribution’. When prompted for the delivery method, select ‘Web’.

The CloudFront control panel

The defaults are usually sufficient for your application, but it is worth taking the time to look at the inline-help for more information on the various options. Note, that if you wish to alias your distribution URL with a CNAME, you must enter the domain under ‘Origin Domain Name’.

You should type the domain name for your application as the ‘Origin Domain Name’. By default, Amazon shows a list of your S3 buckets. This value can be overtyped.

Once created, Amazon will spend a short time setting your distribution up ready for use. This usually takes around five to ten minutes to complete. You are able to track the status of this via the indicators in the CloudFront user interface.

Testing

Now that you have a distribution and your application successfully deployed to Heroku, it is a good idea to test that our distribution is working. To do this, manually select the full URL of one of your static assets, such as a CSS file

http://www.mydomain.com/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

and attempt to request this file through your CloudFront endpoint:

http://d3vam04na8c92l.cloudfront.net/stylesheets/application-6502e5a88f02b90aeb32c2dd21ea37ab.css

This should return you the CSS file as it would be normally returned from your application. If you do not get the file returned as normal, then verify your CloudFront settings are correct, and that you are using the correct domain for your distribution.

Note that CloudFront will only work well with asset file names that are ‘fingerprinted’, e.g. files that have a unique file name based on the content of the file. The reason for this is that CloudFront will see application.css as one file, regardless of how many times you’ve changed the contents, thus leading to users receiving stale versions of that file.

If you are wanting to serve Cloudfront assets using SSL you can simply use HTTPS on the distribution domain given to you by Amazon. Note, whilst you can create CNAME’s for this purpose, serving Cloudfront assets over your CNAME and SSL has an attached cost.

Adding CloudFront to Rails

If you have questions about Ruby on Heroku, consider discussing it in the Ruby on Heroku forums.

For simpler, but less performant, in-application static asset caching see Using Rack::Cache with Memcached in Rails 3.1+ (including Rails 4).

Making Rails serve assets from a Content Delivery Network is simple. Support for CDNs is built into most versions of Rails and requires only a simple change to fully support a CDN.

Within config/environments/production.rb you will see a setting asset_host that is responsible for prepending a domain onto all asset links created via the built in asset helpers.

# config/environments/production.rb
config.action_controller.asset_host = "<YOUR DISTRIBUTION SUBDOMAIN>.cloudfront.net"

Once deployed, this application will now serve all assets through the CloudFront distribution.

Note that only assets linked via the built in helpers (such as image_tag will be prepended. Manually created links will be unaffected. Consult the Rails Asset Pipeline Documentation for more help on these.

Note that CloudFront will respect and mirror the HTTP cache headers that you return from your application. For more information please see Increasing Application Performance with HTTP Cache Headers.