CloudFront is a CND that allow to speed up the delivery of dynamic and static content
Cached content is controlled in the edge locations by using Etags, versioning of an object and cache invalidation

Static and dynamic content

  • Dynamic content is the one that changes according to the user who views it. It can be dependent on the location, device and other factors.

  • Dynamic content helps with personalised experiences for a user

  • Example of dynamic content

    • website that displays different offers, recommendations
    • blogs with different posts, comments, ads
    • gaming
  • Dynamic content is hard/very difficult to store in the edge location because results would be outdated very quickly.

  • Static content is fixed and doesn’t change very often

  • Examples

    • logos
    • contact page
    • banners
    • CSS

Cache Invalidation

Cache invalidation invalidates the cache and clears it from the edge caches before expiration time. It allows to get the most recent version of static files. However, invalidation of files won’t necessary mean that the user will see recent files, because they might be cached in a browser. For that reason, a hash or a timestamp should be added to files.

How Cache Invalidation works

A user requests a file, the CDN does not have it so it caches it with an Etag header

TTL

  • Time To Live and determinates how long CloudFront caches an object at the edge location before checking origin
  • If TTL = 0, it means that it does not cache the object at all
  • Default TTL is what CloudFront uses at the TTL for responses when there’s no Cache-Control header
  • Minimum TTL is the lowest value the CloudFront can use as the TTL
  • Maximum TTL is the highest value that the CloudFront can use as the TTL and overrides whatever value has been set on the origin server.
    The general rule is that you should set those on the origin or to use CloudFront Functions to override them before they are sent to the browser.

Some Other bits

Cache Behaviour allows you to set various things. First of all, you have to to point to the origin so it know what needs to be cache. You do it by setting origin and enabled that is set to true. By setting enabled to true you basically say that the distribution is enabled to accept requests.
aliases - a list of alternate domain names for distribution (www.example.com for example)
default_root_object is a default object that CloudFront should return when user requests root URL (index.html for example)
Cloudfront only suport ACM certificates that are in the us-east-1 region

  • price_class determines which CloudFront edge locations serve your content and there are 3
    • PriceClass_All - Everywhere
    • PriceClass_200 - North America, Europe, South Africa, HK, Singapore, South Korea, Japan, India
    • PriceClass_100 - Europe and North America
  • restrictions specify all restrictions that you want to attach to your CloudFront distribution. This can be geographic location. There are three options
    • none - no restrictions

    • whitelist - locations where you want to distribute content

    • blacklist - locations where you don’t want to distribute content

Cache Behaviour

ordered_cache_behavior {  
  path_pattern = "*"  
  target_origin_id = "my-origin"  
  viewer_protocol_policy = "redirect-to-https"  
  allowed_methods = ["GET", "HEAD"]  
  cached_methods = ["GET", "HEAD"]  
  min_ttl = 0  
  default_ttl = 3600  
  max_ttl = 86400  
  forwarded_values {  
    query_string = false  
    cookies {  
      forward = "none"  
    }  
  }  

forwarded_values allow to ignore query strings and cookies when forwarding request to the orgin and not include them in cache. It’s good when your static content does not depend on them in viewer requests (for example, files don’t change based on query strings or cookies etc)
allowed_methods controls which HTTP methods CloudFront processes and forwards to the origin
cached_methods controls whether CloudFront caches the response to requests
viewer_protocal_policy controls the protocl that viewers can use to communicate with CloudFront

  • allow-all: Viewers can use both HTTP and HTTPS protocols. CloudFront does not redirect HTTP requests to HTTPS.
  • redirect-to-https: Viewers can use both HTTP and HTTPS protocols. CloudFront automatically redirects HTTP requests to HTTPS requests. CloudFront returns HTTP status code 301 (Moved Permanently) along with the new HTTPS URL.
  • https-only: Viewers can use only the HTTPS protocol. CloudFront returns HTTP status code 403 (Forbidden) for HTTP requests.

viewer_certificate specifies the SSL/TLS cert to use when requesting the content using HTTPS.

  • cloudfront_default_certificate: A boolean value that indicates whether to use the CloudFront default certificate. This option is valid only if you’re using the CloudFront domain name for your distribution, such as xxxxxxx.cloudfront.net. If you’re using your own domain name, such as example.com, you must specify one of the following options instead: acm_certificate_arn, iam_certificate_id
  • acm_certificate_arn: The Amazon Resource Name (ARN) of the AWS Certificate Manager (ACM) certificate that you want to use for your distribution. This option is valid only if you’re using your own domain name and you have requested or imported a certificate using ACM. You must also specify a value for minimum_protocol_version and ssl_support_method.
  • iam_certificate_id: The ID of the AWS Identity and Access Management (IAM) certificate that you want to use for your distribution. This option is valid only if you’re using your own domain name and you have uploaded a certificate using IAM.

Compression

AWS allows to use gzip and brotli compressions. Brotli delivers up to 24% smaller files compared to gzip which improves the UX and users don’t have to wait for too long.

resource "aws_cloudfront_cache_policy" "example" {  
  name = "example-policy"  
  (...)  
  enable_accept_encoding_brotli = true # This enables brotli compression  
  nable_accept_encoding_gzip = true # This enables gzip compression  
  }  
}  

OAC

  • It is a feature that allows to secure S3 origins by permitting only CloudFront to access buckets.
  • It helps to reduce the number of requests and data tranfers from S3 Bucket
  • It helps to serve from the nearest location instead of fetching i from the S3 Bucket every time
  • It is able to save cost because it needs to fetch the content from S3 when it is not cached or when it expires
    To control access to your CloudFront, you have to setup policy that allows CloudFront to authenticate requests to your origin.
resource "aws_cloudfront_origin_access_control" "example" {  
  name = "example"  
  description = "Example Policy"  
  origin_access_control_origin_type = "s3"  
  signing_behavior = "always"  
  signing_protocol = "sigv4"  
}  

Terraform Setup

# resource "aws_cloudfront_origin_access_identity" "oai" {  
#   comment = "${var.root_domain} OAI"  
# }  
  
# resource "aws_cloudfront_distribution" "cf_distribution" {  
#   depends_on = [aws_s3_bucket.bucket]  
#   origin {  
#     domain_name = aws_s3_bucket.bucket.bucket_regional_domain_name  
#     origin_id   = local.s3_origin_id  
  
#     s3_origin_config {  
#       origin_access_identity = aws_cloudfront_origin_access_identity.oai.cloudfront_access_identity_path  
#     }  
#   }  
  
#   enabled         = true  
#   is_ipv6_enabled = true  
  
#   default_root_object = "index.html"  
  
#   default_cache_behavior {  
#     allowed_methods  = ["GET", "HEAD", "OPTIONS"]  
#     cached_methods   = ["GET", "HEAD"]  
#     target_origin_id = local.s3_origin_id  
  
#     forwarded_values {  
#       query_string = false  
  
#       cookies {  
#         forward = "none"  
#       }  
#     }  
  
#     viewer_protocol_policy = "allow-all"  
#     min_ttl                = 0  
#     default_ttl            = 3600  
#     max_ttl                = 86400  
#     compress               = true  
#   }  
  
#   ordered_cache_behavior {  
#     path_pattern     = "/index.html"  
#     allowed_methods  = ["GET", "HEAD", "OPTIONS"]  
#     cached_methods   = ["GET", "HEAD", "OPTIONS"]  
#     target_origin_id = local.s3_origin_id  
  
#     forwarded_values {  
#       query_string = false  
  
#       cookies {  
#         forward = "none"  
#       }  
#     }  
  
#     min_ttl                = 0  
#     default_ttl            = 0  
#     max_ttl                = 0  
#     compress               = true  
#     viewer_protocol_policy = "allow-all"  
#   }  
  
#   price_class = "PriceClass_100"  
  
#   viewer_certificate {  
#     cloudfront_default_certificate = true  
#   }  
  
#   retain_on_delete = true  
  
#   custom_error_response {  
#     error_caching_min_ttl = var.error_caching_min_ttl  
#     error_code            = 403  
#     response_code         = 200  
#     response_page_path    = "/index.html"  
#   }  
  
#   custom_error_response {  
#     error_caching_min_ttl = var.error_caching_min_ttl  
#     error_code            = 404  
#     response_code         = 200  
#     response_page_path    = "/index.html"  
#   }  
  
#   restrictions {  
#     geo_restriction {  
#       restriction_type = "none"  
#     }  
#   }  
# }