Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Working with Bundler
      • Rails Support
    • Python
      • Background Jobs in Python
      • Working with Django
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with the Play Framework
      • Working with Spring Boot
      • Java Advanced Topics
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
    • Single Sign-on (SSO)
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Add-ons
  • All Add-ons
  • Fastly
Fastly

This add-on is operated by Fastly, Inc

Fastly is a real-time content delivery network that helps businesses scale

Fastly

Last updated 12 June 2020

Table of Contents

  • Installation
  • Fastly API and Control Panel
  • Configuring Custom Domains
  • TLS/SSL
  • General HTTP Caching
  • Framework-Specific configuration
  • Dynamic content caching
  • Verifying Configuration
  • Troubleshooting
  • Migrating between plans
  • Removing the Fastly add-on
  • Support and Community
  • Terms of Service

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.

Installation

A list of plans available can be found on Fastly’s Heroku add-on page.

Fastly can be attached to a Heroku application via the command line interface (CLI):

$ heroku addons:create fastly:fast --app my-fast-app
-----> Adding fastly to my-fast-app... done, v18 ($50/mo)

After installation, three configuration variables are available to your application and can be viewed with heroku config:get.

$ heroku config --app my-fast-app
FASTLY_API_KEY:    XX49d4f5561d401816420e4de34cXX
FASTLY_CDN_URL:    my-fast-app-herokuapp-com.global.ssl.fastly.net
FASTLY_SERVICE_ID: XX9pnrdfuIABx1wpRcAmXX

The Provisioning Process

During the add-on provisioning process, we create a Fastly Service on behalf of your app with the following default configuration:

# Heroku app name: my-fast-app

Service:  my-fast-app
Backend:  my-fast-app.herokuapp.com:80
Domain:   my-fast-app-herokuapp-com.global.ssl.fastly.net

The default configuration works for serving static content over HTTP and HTTPS on the my-fast-app-herokuapp-com.global.ssl.fastly.net domain.

Terminology

  • Service - Holds all configuration about your CDN
  • Backend - The address of the Heroku dyno from which we pull content (sometimes referred to as “Origin”)
  • Domain - The address visitors use to access your app. This is how we know where to route requests.

Fastly API and Control Panel

The Fastly Heroku add-on includes access to https://manage.fastly.com via Heroku SSO and access to Fastly’s API via token authentication.

Fastly’s API and configuration panel both support making configuration changes, viewing real-time and historic CDN stats, and instant purging.

API Documentation is on the docs site and many helpful configuration guides can be found in our guides.

We provide various language clients for interacting with the API.

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:

  1. Clone the active service version
  2. Modify configuration as needed
  3. 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. domain

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.

domain2

Enter the domain you wish to add and click Create. domain3

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

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.

In your DNS provider, CNAME your domain to point to your FASTLY_CDN_URL. Consult our DNS setup guide for step-by-step CNAME instructions for most DNS providers.

If configuring TLS for this domain, wait to CNAME until after completing TLS configuration as the CNAME that you point to will be different.

Once the DNS entry has propagated, clients will be routed to your app through Fastly’s network.

TLS/SSL

Not all pricing plans include TLS Domains. To avoid disappointment, ensure your pricing plan supports TLS Domains before attempting to provision TLS.

The default Fastly configuration supports TLS over HTTPS out of the box on your .global.ssl.fastly.net domain. To enable TLS on a custom domain, use our Heroku CLI Plugin to provision TLS.

The CLI Plugin can be installed with:

$ heroku plugins:install @fastly/heroku-plugin
Installing plugin heroku-fastly... done

Usage and examples can be found using help:

$ heroku fastly:tls help
Usage: heroku fastly:tls DOMAIN --app APP
...

To add a TLS Domain:

$ heroku fastly:tls www.my-fast-app.com --app my-fast-app
=== Domain www.my-fast-app.com has been queued for TLS certificate addition. This may take a few minutes.
 ▸    In the mean time, you can continue by starting the domain verification process.

 ▸    Create a DNS TXT record for your domain containing the following content:
 ▸
 ▸   domain-verification=xYZ789SoMeRad0MStr1ng123

This queues your domain for TLS provisioning.

The requested domain must be configured in the active version of your service to successfully provision. If this is not the case, you will see the following error: Domain does not exist in your service configuration! You must configure this domain in your service to use.

When the command completes you will need to verify ownership of your domain by adding the provided TXT record to your DNS configuration via your DNS provider.

After adding the TXT record and waiting for DNS propagation (if needed, based on your TTL), run the following command to kick off the domain verification process:

$ heroku fastly:verify start www.my-fast-app.com --app my-fast-app
 ▸    Valid approval domains: my-fast-app.com,www.my-fast-app.com
Type the approval domain to use (or ENTER if only 1): : www.my-fast-app.com
 ▸    Domain queued for verification. This takes approximately 30 minutes. To check the status, run 'heroku fastly:verify status <domain> --app <app_name>'

Due to current limitations with our CA, domain verification may take up to 30 minutes. You can check the status of verification using the following command:

$ heroku fastly:verify status www.my-fast-app.com --app my-fast-app
 ▸    State:issued
 ▸    Your cert has been issued, but it may take 30 minutes or longer to become available globaly. To check availability, you can test your domain at 'https://www.ssllabs.com/ssltest/'
 ▸
 ▸    Configure the following CNAME when the cert becomes available:
 ▸
 ▸    CNAME  www.my-fast-app.com  foo.bar.ssl.fastly.net

Please note that just because verification has completed, the new certificate may not yet be propagated to all global cache nodes. This may take upwards of 30 minutes. To ensure no disruption in service, you should wait approximately 30 minutes before updating your CNAME and check the ssl status of your domain using https://www.ssllabs.com/ssltest/

If domain verification has completed, the above command will output the CNAME that you’ll need to update your domain to point at. After updating the CNAME of your domain, TLS should be enabled on that domain.

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.

A typical Cache-Control header looks like:

Cache-Control: public, s-maxage=2592000, max-age=86400

In the Cache-Control directives above:

  • public specifies this content can be cached
  • s-maxage specifies a 30 day TTL for surrogate caches (e.g. a CDN edge cache)
  • max-age specifies a 24 hour TTL for other caches (e.g. browser cache)

A full list of directives is available in the specs linked above. For further explanation and examples relating to Fastly, read our cache control tutorial.

Framework-Specific configuration

Rails (3.1+)

For static content (things like CSS, JavaScript, images) use Rails’ asset pipeline to control cache behavior. For an more detailed guide on using Fastly with Rails check out Accelerating Rails, Part 1 and Accelerating Rails, Part 2.

To set TTLs on static content, modify config/environments/production.rb:

config.static_cache_control = 'public, s-maxage=2592000, max-age=86400'

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.

For brevity we leave the details on asset digests to the Rails Asset Pipeline Fingerprinting guide and just note the configuration option required to enable digests.

config.assets.digest = true

Sinatra

To cache static assets with Sinatra, we recommend the sinatra-asset-pipeline gem, which adds a Sprockets integration to Sinatra, much like the Rails asset pipeline.

Following from the Rails asset pipeline configuration above, you can set cache control headers and digests.

We recommend using the rack-cache middleware to configure cache settings. It’s also a good idea to use the Rack::Deflater middleware to compress responses.

Node

You can incorporate the express-cdn Node.js module to set up Fastly static asset caching with your Node.js applications.

The express-cdn docs do not explicitly call out use with Fastly, but it works exactly the same as their docs demonstrate.

In your app.js file (see this example) set the domain attribute to your FASTLY_CDN_URL (e.g., my-fast-app-herokuapp-com.global.ssl.fastly.net) or your custom domain, if using one.

var options = {
    publicDir  : path.join(__dirname, 'public')
  , viewsDir   : path.join(__dirname, 'views')
  , domain     : process.env.FASTLY_CDN_URL
  , ...
  , production : true
};

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:

  1. Generate cache keys that map to a single object or related set of objects
  2. Include Cache-Control and Surrogate-Key headers on HTTP GET responses
  3. Issue a purge request with the resource’s cache key when the object changes (usually on HTTP POST, PUT, DELETE)

Surrogate-Keys are HTTP headers that Fastly uses to associate cache keys with response objects.

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:

http://fastly-test.global.ssl.fastly.net/assets/application-048b5b7c55e3a7429fda3.css

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:

http://my-fast-app.herokuapp.com/assets/application-048b5b7c55e3a7429fda3.css

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 application 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:

HTTP/1.1 200 OK
...
Cache-Control: public, s-maxage=2592000, max-age=86400
...
Via: 1.1 varnish
Age: 12
X-Served-By: cache-sjc3127-SJC
X-Cache: HIT
X-Cache-Hits: 1
X-Timer: S1406260210.511119,VS0,VE0

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.

Use the heroku addons:upgrade command to migrate to a new plan:

$ heroku addons:upgrade fastly:pro
-----> Upgrading fastly:pro to sharp-mountain-4005... done, v18 ($100/mo)
       Your plan has been updated to: fastly:pro

Removing the Fastly add-on

Removing the Fastly add-on will destroy all cached content and service configuration. This cannot be undone!

Fastly can be removed via the CLI:

$ heroku addons:destroy fastly
-----> Removing fastly from sharp-mountain-4005... done, v20 ($50/mo)

Support and Community

Fastly provides a Discourse-powered community forum for questions and troubleshooting.

Support is also available through other channels.

You can always find us in #fastly on freenode IRC or on Twitter at @Fastly.

Terms of Service

By installing the Fastly Add-on, you agree to the Fastly Terms of Service.

Keep reading

  • All Add-ons

Feedback

Log in to submit feedback.

Ziggeo Felix Cloud Storage

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies