Fastly is the world’s smartest content delivery network. The Fastly Heroku add-on provides a quick and easy way to add the power of Fastly’s global content delivery network (CDN) to Heroku applications.

This document covers configuration of static and dynamic edge caching with Fastly for Heroku applications.

All Fastly configuration changes are versioned so that if a mistake is made, it can quickly be rolled back to a working version. In general, the process of modifying a configuration setting is:

Clone the active service version

Modify configuration as needed

Activate the cloned version

Once a version is activated, it becomes locked and can no longer be modified.

Configuring Custom Domains

The .global.ssl.fastly.net domain created during provisioning works out of the box, but you may want to use a more friendly looking URL.

For example, to use the custom domain www.my-fast-app.com instead of the Heroku provided domain my-fast-app.herokuapp.com you add that domain to your Heroku configuration.

In the same way, to use that domain with Fastly, you configure it in your Fastly service. This can be done by using SSO to login to our configuration dashboard.

Navigate to the Configure tab and click the blue Configure button.

Click on Domains in the left menu and then the green New button.

A non-active version must be selected. Each time a version is activated, a new version is automatically created for you. You can change the version by selecting from the dropdown next to the Clone button.

Enter the domain you wish to add and click Create.

The domain now appears in the list of domains. Click the yellow Activate button to make the configuration change live.

To use TLS/SSL with this domain, follow the instructions below in the TLS/SSL section.

CNAME to Fastly

Although not required to use Fastly, we recommend you CNAME your app’s top-level domain to Fastly for the best performance. CNAME-ing will direct all requests through Fastly, providing a performance boost out of the box. CNAMEs are described in some depth in Part 2 of our blog on Accelerating Rails.

The requested domain must be configured in the active version of your service to successfully provision.

When the command completes you will need to verify ownership of your domain using one of the supported verification types - email, dns, or URL. Details on domain verification can be found in the help documentation of the heroku-fastly CLI plugin. After verification we will complete the TLS provisioning process automatically. This typically takes a few minutes.

To remove a TLS Domain:

$ heroku fastly:tls -r www.my-fast-app.com --app my-fast-app

All TLS domains are automatically removed upon removal of the Fastly add-on.

General HTTP Caching

As a CDN, Fastly provides infrastructure to accelerate your applications. We put Points of Presence (POPs) all over the world and run a highly optimized network to reduce latency to end-clients. It’s helpful to know a little about HTTP performance and optimization before starting. If you’re familiar with HTTP Caching, feel free to skip to the next section.

Cache control headers

HTTP Cache-Control and Surrogate-Control headers tell Fastly what content to cache and for how long to cache it. Correctly setting cache control headers on application responses can significantly impact performance. As such, we encourage you to consider what values make the most sense for your application. In general, the longer an object’s TTL (time to live), the higher the cache hit ratio, meaning less requests back to your dynos and better response time to clients.

If you have content in the /public directory that you want Fastly to cache, you may also need to set:

config.serve_static_assets = true

If you configured a custom domain with a CNAME pointing to Fastly, you don’t need to worry about configuring an asset_host since all requests will route through Fastly. Just ensure cache control headers are being set correctly with the above static_cache_control option.

If you did not configure a custom domain, you can use the FASTLY_CDN_URL config var as your asset_host. For example, in config/environments/production.rb (usually commented out by default):

config.action_controller.asset_host = ENV['FASTLY_CDN_URL']

Asset Digests

Asset digests (aka “fingerprinting”) is a way to eliminate the need to invalidate cached assets when they change. Although Fastly supports instant purging, many developers like to use digests so they don’t have to do any invalidation upon deploying new assets.

Python (Django)

If you’re using django-static you can specify the MEDIA_URL as your FASTLY_CDN_URL.

Dynamic content caching

Fastly enables rapidly changing dynamic content like REST APIs and dynamic HTML to be cached at the edge. There are a couple different approaches to dynamic content caching outlined in the “Cache Strategies” section of Part 2 of our Accelerating Rails blog.

Fastly can integrate into your application framework to leverage dynamic caching that takes advantage of our instant purge API. We provide various framework-specific plugins, listed below, to make it quick and easy to set up.

Dynamic caching can be integrated into an HTTP endpoint in three steps:

Generate cache keys that map to a single object or related set of objects

Include Cache-Control and Surrogate-Key headers on HTTP GET responses

Issue a purge request with the resource’s cache key when the object changes (usually on HTTP POST, PUT, DELETE)

We’ve written a blog post that explains more about caching dynamic content. In addition, our API caching blog post series is a good place to read about dynamic API caching in more depth.

Rails

We maintain the Fastly Rails plugin to cache dynamic content with Rails. The plugin contains helpers for creating cache keys, setting the required headers, and issuing purges. Check out this blog by thoughtbot on the plugin.

Node

A community maintained Fastly npm package wraps our purge API that you can leverage in NodeJS applications.

Drupal

We maintain a Drupal plugin that automatically integrates with our purge API. The module can be downloaded from the link and installed into your site. Check out the blog on drupal.org to learn more.

Wordpress

A community maintained Wordpress plugin called Purgely is available in the Wordpress Plugin Directory that automatically integrates with our purge API. The source is available on Github. Check out this blog on crate.io to learn more.

Other

Want to integrate Fastly dynamic caching into a framework not listed here? Let us know! We love making it easy for all developers to integrate with Fastly.

Verifying Configuration

Make sure you’ve deployed the code changes listed above that configure your application for use with Fastly.

Caching can sometimes be confusing. The following outlines a few steps to help verify your Fastly configuration is working as expected. Also check out our guide on testing your setup.

Verifying static content

You can verify static assets are served from the CDN by viewing your application in the browser and viewing source. Any assets served by an asset pipeline such as a application.css in a Rails app should be coming from the domain that matches your FASTLY_CDN_URL such as:

If the domain does not match the current value of your FASTLY_CDN_URL you should double check that your application and assets are configured correctly and that the most recent code changes have been deployed. If you’re using a custom domain and did not configure a static asset host, you should see your custom domain here.

If you see the right URL but the wrong content, try viewing that content directly by copying and pasting your asset URL into your browser’s address bar. If you are getting an error, verify that your application is serving the right content. You can do this by taking the path in this example /assets/application-048b5b7c55e3a7429fda3.css, and trying to view that file from your own domain instead of through the CDN. So if your application was hosted on my-fast-app.herokuapp.com you could visit:

If the asset fails to load (with a 503 status code), there is probably nothing wrong with your Fastly configuration, but rather the problem likely exists in your application. Ensure your application is serving the asset and check deploy logs to make sure there were no errors.

Another handy tool is to verify the files exist on the dyno as you expect. You can do this by running:

$ heroku run bash

Then poke around the filesystem with cd and ls to verify the presence of files and cat to verify the content.

If your application is serving the correct file but it’s not going through the CDN, you can try issuing a “Purge All” from the Fastly control panel or the CLI plugin. This clears all content from the cache and subsequently forces an update by making requests to your dynos.

Use “Purge All” with caution! It may take a long time to refill the cache and/or applicaion dynos may see higher load as a result of the cache filling up.

Verifying dynamic content

Use curl to make a request to your application and verify that the response contains certain cache related headers.

curl -I https://www.my-fastly-app.com/path/to/content.json

If the request went though Fastly, you should see response headers that look like:

If your response doesn’t include the Via and X-Cache* headers, something is configured incorrectly.

Troubleshooting

Below are solutions to a few issues sometimes encountered during setup.

Content not found and 404’s

As long as the content is available from the application, we will never return a 404 (due to the “proxy” nature of the Fastly edge caches). If you’re seeing a 404 and are positive the content is available from your dyno, it’s possible we cached a 404 (see HTTP status codes cached by default) when the content may not have been available. In this case, purge the object that is 404'ing to force a cache refresh.

Redirect loops and forcing HTTP to HTTPS

If your application forces redirects from HTTP to HTTPS and upon installation of Fastly you see redirect loops coming from the cache, this is because you need to configure Fastly to pull content from your apps over HTTPS. By default we cache 301 redirects, which causes this redirect loop to happen.

You can fix this by updating the port of your Backend to 443 (default is 80) in the Fastly configuration panel. Depending on what TTL value you use, you may need to wait for the 301 redirects to expire in the cache or issue a Purge. A Purge will force a refresh - removing the cached 301 and subsequently updating with the actual content, which will now be pulled over port 443 (the port used with SSL).

Expired assets

It is possible for our caches to serve an expired asset if the client makes a request for an expired asset and the application dyno is unavailable. You can tune this by setting the TTL (cache expiration time) with cache control headers and using stale-if-error/stale-while-revalidate directives.

Cross-origin resource sharing (CORS)

If you encounter trouble loading assets (such as fonts, especially in FireFox) that are hosted somewhere other than your application dynos, you should first ensure that the host is correctly setting the Access-Control-Allow-Origin header. If you have verified your configuration and the problem persists, you can set a CORS Access-Control-Allow-Origin header at the edge via the Fastly control panel.

Pricing and Overages

Based on the pricing plan you select, Fastly charges a monthly flat rate for CDN service. Each pricing plan includes a fixed amount of bandwidth and requests. Be sure to choose a plan that roughly corresponds to your site’s traffic profile, as we take overages seriously.

We send ample warning emails when approaching plan limits along with ample overage emails. If significantly more bandwidth is used than what’s included in your plan, we may temporarily discontinue service at anytime during the period of overage.

Migrating between plans

You can migrate between plans at any time. Migrating to a different plan will change bandwidth and request limits, but does not affect any cached content.