Using Amazon CloudFront CDN
Last updated July 24, 2019
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.
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.
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
Note that by using a DNS CNAME record, we can hide this domain behind something from our application e.g.
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.
Creating a distribution
If you wish to avoid provisioning AWS resources yourself, you can use 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 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.
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
and attempt to request this file through your CloudFront endpoint:
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
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.
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.
If you are loading all the assets on your site via a CDN then the browser may give warnings or errors about using resources from different origins. Firefox in particular may complain when serving assets:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource .
There is a mechanism that allows you to communicate to the browser which assets can be loaded at specific origins safely. This is known as cross origin resource sharing or CORS. It works by setting specific headers when serving the assets. CloudFront caches headers when it caches your assets so if your app serves assets with the appropriate CORS headers then CloudFront will cache them and serve them. You can set headers using ActionDispatch::Static in Rails 5 or via rack-cors gem.