DEV Community

Sohana Akbar
Sohana Akbar

Posted on

CloudFront Invalidations from CI: Automate Cache Clears

If you've ever deployed a website to S3 and CloudFront, you know the frustration: you push your changes, wait a minute, refresh the page, and... still see the old version. 😅

The problem is CloudFront caching—it's great for performance, but it means users can see stale content after you deploy updates . By default, CloudFront serves cached content until it expires (up to 24 hours!) .

The solution? Automate CloudFront cache invalidation from your CI/CD pipeline. Let's break down why and how.

Why Automate Invalidation?
Doing invalidations manually through the AWS Console is:

❌ Error-prone (forgetting to do it)

❌ Slow (breaks your deployment flow)

❌ Not scalable (as your team grows)

Automating invalidation ensures users always see the latest content immediately after deployment .

The Core Command
Whether you use GitHub Actions, Jenkins, or AWS CodePipeline, the underlying AWS CLI command is the same:

bash
aws cloudfront create-invalidation \
--distribution-id EDFDVBD6EXAMPLE \
--paths "/"
The --paths parameter supports wildcards—/
invalidates everything, while /index.html or /assets/* invalidates specific paths .

CI/CD Integration Patterns

  1. GitHub Actions This is probably the most popular approach. In your workflow YAML, add a step to create the invalidation after your deployment:

yaml

  • name: Invalidate CloudFront run: | aws cloudfront create-invalidation \ --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \ --paths "/*" env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-east-1 Store your distribution ID and AWS credentials as GitHub Secrets .
  1. AWS CodePipeline with Lambda CodePipeline can trigger a Lambda function after S3 sync, which then creates the invalidation :

python
import boto3

def lambda_handler(event, context):
cloudfront = boto3.client('cloudfront')
response = cloudfront.create_invalidation(
DistributionId='YOUR_DISTRIBUTION_ID',
InvalidationBatch={
'Paths': {
'Quantity': 1,
'Items': ['/*']
},
'CallerReference': str(event.get('timestamp', 'manual'))
}
)
return response

  1. Terraform The aws_cloudfront_distribution resource doesn't natively support invalidation. However, you can use local-exec provisioner as a workaround :

hcl
resource "aws_cloudfront_distribution" "s3_distribution" {
# ... configuration ...

provisioner "local-exec" {
command = "aws cloudfront create-invalidation --distribution-id ${self.id} --paths '/*'"
}
}
⚠️ Note: This runs after resource creation, but for every terraform apply, consider using a null_resource with triggers for more control.

  1. Jenkins Pipeline Similar to GitHub Actions—just call the AWS CLI from your Jenkinsfile:

groovy
stage('Invalidate Cache') {
steps {
sh '''
aws cloudfront create-invalidation \
--distribution-id ${CLOUDFRONT_DIST_ID} \
--paths "/*"
'''
}
}

  1. Package.json Scripts For smaller projects, you can chain commands in npm scripts :

json
{
"scripts": {
"build.prod": "ng build --prod --aot",
"aws.deploy": "aws s3 sync dist/ s3://www.mywebsite.com --delete",
"aws.invalidate": "aws cloudfront create-invalidation --distribution-id [ID] --paths /",
"deploy": "npm run build.prod && npm run aws.deploy && npm run aws.invalidate"
}
}
IAM Permissions
Your CI user needs at minimum:

json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["cloudfront:CreateInvalidation"],
"Resource": "*"
}]
}
If you need to wait for completion (e.g., for testing), add cloudfront:GetInvalidation .

Best Practices & Considerations
Don't invalidate everything every time. If only index.html and main.js change, invalidate just those paths to be more efficient .

Cache invalidation costs money. The first 1,000 paths per month are free; after that, it's charged . Invalidate with intention.

Consider using versioned filenames (e.g., main.a1b2c3.js) so you can keep caching forever and invalidate only the entry point. This is how modern frameworks roll.

Wait for completion? Some plugins (like ember-cli-deploy-cloudfront) offer a waitForInvalidation flag, but this can take several minutes—only use it when absolutely necessary .

Real-World Example
A typical CI/CD flow looks like this :

Developer pushes code to GitHub

GitHub Actions/AWS CodePipeline triggers build

Build assets are uploaded to S3

CloudFront invalidation runs automatically

Users see fresh content instantly

No manual steps. No stale cache. 🚀

Summary
CloudFront invalidations are a necessary evil when deploying sites with a CDN. The good news is that automating them is straightforward with any CI/CD tool—GitHub Actions, AWS CodePipeline, Jenkins, or Terraform.

Choose the approach that fits your stack, add the invalidation step to your pipeline, and never think about stale cache again.

What's your preferred way to handle CloudFront invalidations? Drop a comment below!

Top comments (0)