You are in full control of how Fastly caches your resources. The preferred way is to use backend HTTP headers. The other way is to use the Varnish Configuration Language (VCL).
Backend HTTP headers
You can set four different types of HTTP headers which will have different effects on our caches and on web browsers. If you use more than one type, they are prioritized in the order listed below:
Surrogate-Control
Format:
1
Surrogate-Control: max-age=(time in seconds)
Example:
1
Surrogate-Control: max-age=3600
will cache something on our caches for one hour. This header gets stripped and is only visible to Fastly caches.
Cache-Control: s-maxage
Format:
1
Cache-Control: s-maxage=(time in seconds)
This is the same as Surrogate-Control
, except the header is not stripped and will be respected by Fastly caches and any caches between Fastly and the browser, but not the browser itself.
Cache-Control: max-age
Format:
1
Cache-Control: max-age=(time in seconds)
This header will be respected by Fastly caches, any caches between Fastly and the browser, and the browser itself.
Expires
This header caches content until it expires as specified. It will be respected by Fastly caches, any caches between Fastly and the browser itself. See section 5.3 of RFC7234 for an explanation of the format.
Do not cache
If you want to ensure that a resource is not cached by Fastly, send the following HTTP header with the origin response:
1
Cache-Control: private
If you just set max-age=0
or an Expires
in the past, Fastly may still use a single response to satisfy multiple outstanding requests that arrive while waiting on the origin (see Request collapsing), or may cache the object in a stale form so that it can be used in case of errors or asynchronous revalidation (see Serving stale content).
The private
directive does not prevent content from being cached in the browser. If you need to prevent caching by both Fastly and web browsers, we recommend combining the private
directive with max-age=0
or no-store
. For example:
1
Cache-Control: private, no-store
Fastly does not currently respect no-store
or no-cache
directives. Including either or both of these in a Cache-Control
header has no effect on Fastly's caching decision, unless you alter this behavior using custom VCL.
Applying different cache rules for Fastly and browsers
Say you want Fastly to cache your content but you don't want it cached by browsers. The best way to do this would be to send Fastly both the Cache-Control
header as you want it to go to the browsers, and use Surrogate-Control
to tell us how long to cache for. For example:
1
2
Cache-Control: no-store, must-revalidate
Surrogate-Control: max-age=3600
Except for when the Cache-Control
header is set to private
, the Surrogate-Control
header takes priority over Cache-Control
, but unlike Cache-Control
it is stripped so the browsers don't see it.
Configuring popular web servers
Apache Config
If you are using Apache, the easiest way to add headers is to use the mod_expires module. For example, to cache GIF images for 75 minutes after the image was last accessed by the cache server, you would add a directive like this under the VirtualHost (or globally). For example:
1
2
ExpiresActive On
ExpiresByType image/gif "access plus 1 hours 15 minutes"
You can also cache whole URL subtrees. For example:
1
2
3
4
5
6
7
8
9
<Location "/css">
ExpiresActive On
ExpiresDefault "access plus 1 year"
</Location>
<Location "/static/">
ExpiresActive On
ExpiresDefault "access plus 1 day"
</Location>
NGINX Configuration
To configure NGINX, add the expires directive. For example:
1
2
3
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1h;
}
Alternatively, if you need more flexibility in modifying headers you can try the HttpHeadersMore Module.
Amazon S3 configuration
By default, S3 doesn't have a facility for setting Cache-Control headers across multiple objects, so you will have to do this resource-by-resource using the S3Explorer, or in an automated fashion by using a cloud library like boto. Remember that you can combine long cache time with instant purges to enhance your performance.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from boto.s3.connection import S3Connection
connection = S3Connection('aws access key', 'aws secret key')
buckets = connection.get_all_buckets()
for bucket in buckets:
for key in bucket.list():
print('%s' % key)
if key.name.endswith('.jpg'):
contentType = 'image/jpeg'
elif key.name.endswith('.png'):
contentType = 'image/png'
else:
continue
key.metadata.update({
'Content-Type': contentType,
'Cache-Control': 'max-age=864000'
})
key.copy(
key.bucket.name,
key.name,
key.metadata,
preserve_acl=True
)
IMPORTANT: The above example provides an S3 configuration option for customers with small- to medium-sized buckets. However, it iterates over every object in those buckets. If you have millions of objects this may not be the right approach. For millions of objects, we recommend using VCL. Be sure to contact us for assistance.
Custom Headers in Programming Languages and Frameworks
PHP
More information: https://php.net/manual/en/function.header.php
Example: add this to your PHP code before you send any output to cache certain HTML for an hour.
1
header('Cache-Control: max-age=3600');
Django
More information: https://docs.djangoproject.com/en/dev/ref/request-response/#setting-headers
Example:
1
2
response = HttpResponse()
response['Cache-Control'] = 'max-age=3600'
Sinatra
More information: http://sinatrarb.com/documentation.html
Example:
1
2
3
get '/' do
headers['Cache-Control'] = 'max-age=3600'
end
TIP: Expiration times in these examples are provided for guidance only. You can use longer expirations coupled with our purging API to make your site faster and your backend less loaded.