Amazon Cloudfront Cache-Control: no-cache header has no effect after 24 hours

Verify that the CloudFront distribution's Minimum TTL is set to 0. If it's set to any other value, CloudFront won't respect the no-cache header and will still cache the file for the Minimum TTL. More details about the caching directives can be found here:

http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html

If this doesn't help, try to debug the actual HTTP request for index.html and post the response headers here so we can have a look at them.

Also, instead of using no-cache for the index.html file, you can try using

public, must-revalidate, proxy-revalidate, max-age=0

This will allow CloudFront to store the file on the edge location, but it will force it to revalidate it with the origin with each request. If the file hasn't changed, CloudFront will not need to transfer the file's entire content from the origin. This can speed up the response time, especially for larger files.


This is more of a comment, but a bit too long. Hopefully helps others that land here.

Cache busting via query parameter has drawbacks, although perhaps you can combat them all via Cloudfront behaviors. See https://stackoverflow.com/a/24166106/630614. Still, I would recommend unique filenames e.g. app.css?v=14113e2c764 becomes app.14113e2c764.css.

To respond to BradLaney's comment/issue: If you've updated cache-control headers and don't see the changes, it's because the origin item is already cached – invalidate it and you should see the new headers the next time you view the resource.

Regarding race condition when setting cache-control for S3 items, or just setting cache-control in general for an SPA, this is what's working well for my team:

# Sync all files with 1 week cache-control, excluding .html files.
aws s3 sync --cache-control 'max-age=604800' --exclude *.html dist/ s3://$AWS_BUCKET/
# Sync remaining .html files with no cache.
aws s3 sync --cache-control 'no-cache' dist/ s3://$AWS_BUCKET/