Skip to content
Back to skills

Aws Cloudfront Optimization

ASecurity

AWS CloudFront — distribution configuration, cache policies, origin access, Lambda@Edge, performance optimization, and security.

  • 6 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added June 1, 2026
ai-agentsjavascriptjavabashawsapisecurityperformance

Works with

  • api

Security analysis

A100/100

Scanned June 1, 2026

npx -y skills add KevinZai/commander --skill aws-cloudfront-optimization --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Aws Cloudfront Optimization?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Aws Cloudfront Optimization
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kevinzai-aws-cloudfront-optimization/badge)](https://www.skillsdirectory.com/skills/kevinzai-aws-cloudfront-optimization)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: aws-cloudfront-optimization
description: "AWS CloudFront — distribution configuration, cache policies, origin access, Lambda@Edge, performance optimization, and security."
risk: low
source: custom
date_added: '2026-03-20'
---

# AWS CloudFront Optimization

Expert guide to CloudFront CDN configuration and performance optimization.

## Use this skill when

- Setting up CloudFront distributions for static assets, SPAs, or APIs
- Optimizing cache hit ratios and reducing origin load
- Implementing Lambda@Edge or CloudFront Functions
- Securing content delivery with WAF, geo-restrictions, or signed URLs

## Do not use this skill when

- Using Cloudflare, Fastly, or other CDN providers
- Simple S3 static website without CDN requirements

---

## Distribution with S3 Origin (OAC)

```hcl
resource "aws_cloudfront_distribution" "main" {
  enabled             = true
  is_ipv6_enabled     = true
  default_root_object = "index.html"
  price_class         = "PriceClass_100"  # US, Canada, Europe only
  aliases             = [var.domain_name]

  origin {
    domain_name              = aws_s3_bucket.assets.bucket_regional_domain_name
    origin_id                = "s3-assets"
    origin_access_control_id = aws_cloudfront_origin_access_control.main.id
  }

  # API origin
  origin {
    domain_name = "api.${var.domain_name}"
    origin_id   = "api"

    custom_origin_config {
      http_port              = 80
      https_port             = 443
      origin_protocol_policy = "https-only"
      origin_ssl_protocols   = ["TLSv1.2"]
    }
  }

  # SPA: route all paths to index.html
  custom_error_response {
    error_code         = 403
    response_code      = 200
    response_page_path = "/index.html"
  }
  custom_error_response {
    error_code         = 404
    response_code      = 200
    response_page_path = "/index.html"
  }

  # Static assets — long cache
  default_cache_behavior {
    allowed_methods        = ["GET", "HEAD", "OPTIONS"]
    cached_methods         = ["GET", "HEAD"]
    target_origin_id       = "s3-assets"
    viewer_protocol_policy = "redirect-to-https"
    compress               = true

    cache_policy_id          = aws_cloudfront_cache_policy.assets.id
    origin_request_policy_id = aws_cloudfront_origin_request_policy.cors.id

    function_association {
      event_type   = "viewer-response"
      function_arn = aws_cloudfront_function.security_headers.arn
    }
  }

  # API paths — no caching
  ordered_cache_behavior {
    path_pattern           = "/api/*"
    allowed_methods        = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods         = ["GET", "HEAD"]
    target_origin_id       = "api"
    viewer_protocol_policy = "https-only"
    compress               = true

    cache_policy_id          = data.aws_cloudfront_cache_policy.disabled.id
    origin_request_policy_id = data.aws_cloudfront_origin_request_policy.all_viewer.id
  }

  viewer_certificate {
    acm_certificate_arn      = aws_acm_certificate.main.arn
    ssl_support_method       = "sni-only"
    minimum_protocol_version = "TLSv1.2_2021"
  }

  web_acl_id = aws_wafv2_web_acl.main.arn

  tags = local.common_tags
}
```

## Cache Policies

```hcl
resource "aws_cloudfront_cache_policy" "assets" {
  name        = "${var.project}-assets-cache"
  default_ttl = 86400     # 1 day
  max_ttl     = 31536000  # 1 year
  min_ttl     = 0

  parameters_in_cache_key_and_forwarded_to_origin {
    cookies_config {
      cookie_behavior = "none"  # Don't vary cache by cookies
    }
    headers_config {
      header_behavior = "none"  # Don't vary by headers
    }
    query_strings_config {
      query_string_behavior = "none"  # Don't vary by query strings
    }
    enable_accept_encoding_brotli = true
    enable_accept_encoding_gzip   = true
  }
}
```

## CloudFront Functions (Viewer-Side)

```javascript
// Security headers function
function handler(event) {
  var response = event.response;
  var headers = response.headers;

  headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubDomains; preload' };
  headers['x-content-type-options'] = { value: 'nosniff' };
  headers['x-frame-options'] = { value: 'DENY' };
  headers['x-xss-protection'] = { value: '1; mode=block' };
  headers['referrer-policy'] = { value: 'strict-origin-when-cross-origin' };
  headers['permissions-policy'] = { value: 'camera=(), microphone=(), geolocation=()' };

  return response;
}
```

```javascript
// URL rewrite for SPA (cleaner than custom error responses)
function handler(event) {
  var request = event.request;
  var uri = request.uri;

  // If URI has no extension, serve index.html (SPA routing)
  if (!uri.includes('.')) {
    request.uri = '/index.html';
  }

  return request;
}
```

## Cache Invalidation

```bash
# Invalidate specific paths
aws cloudfront create-invalidation \
  --distribution-id E1234567890 \
  --paths "/index.html" "/assets/main.css"

# Invalidate everything (expensive at scale)
aws cloudfront create-invalidation \
  --distribution-id E1234567890 \
  --paths "/*"
```

### Cache Busting Strategy (Preferred over Invalidation)

```
# Use content hashes in filenames — never needs invalidation
assets/main.a1b2c3d4.js     # Cached forever
assets/styles.e5f6g7h8.css  # Cached forever
index.html                   # Short TTL (5 min) or no-cache
```

## Performance Optimization Checklist

- [ ] Compression enabled (Brotli + Gzip)
- [ ] Cache policy tuned per path pattern (assets: long TTL, API: no cache, HTML: short TTL)
- [ ] Content-hashed filenames for static assets (cache forever, no invalidation)
- [ ] HTTP/2 and HTTP/3 enabled (default)
- [ ] Origin Shield enabled for multi-region origins
- [ ] Price class appropriate for audience geography
- [ ] Connection keep-alive on custom origins

## Common Pitfalls

1. **Caching API responses** — Use `CachingDisabled` policy for API paths.
2. **No compression** — Enable both Brotli and Gzip. Saves 60-80% bandwidth.
3. **Invalidation as deployment strategy** — Use content-hashed filenames instead.
4. **Missing CORS headers** — Configure origin request policy to forward `Origin` header.
5. **No WAF** — Attach WAF Web ACL for rate limiting, IP blocking, and bot protection.
6. **Overly broad cache policies** — Forwarding cookies/query strings to cache key reduces hit ratio.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…