Skip to content
C Codeloom
AWS

AWS CloudFront Basics: CDN for S3 and Beyond

Learn how Amazon CloudFront works: origins, distributions, cache behaviors, invalidations, signed URLs, and pairing CloudFront with S3 for static sites.

·6 min read · By Yash Kesharwani
Intermediate 10 min read

What you'll learn

  • What CloudFront does and how its edge network is laid out
  • How origins and distributions are configured
  • How cache behaviors control TTLs and request handling
  • When to use invalidations and signed URLs
  • How to pair CloudFront with S3 for fast static hosting

Prerequisites

  • Familiarity with [What is AWS](/blog/what-is-aws)
  • Comfort with [S3 basics](/blog/aws-s3-basics) and HTTP concepts

Amazon CloudFront is AWS’s content delivery network (CDN). It puts cached copies of your content in over 600 edge locations worldwide so users get fast responses regardless of where your origin lives. CloudFront is also one of the cheapest ways to put HTTPS, custom domains, and DDoS protection in front of any backend.

This article walks through the building blocks: distributions, origins, behaviors, invalidations, and signed URLs — with a focus on the S3-backed static site, which is the most common starting point.

Distributions and origins

A distribution is the top-level CloudFront resource. It is what you point your DNS at. Each distribution gets a domain name like d111abc222def3.cloudfront.net, and you can attach custom domains via Route 53 and ACM certificates.

Inside a distribution, you configure one or more origins. An origin is the source CloudFront fetches from when it has a cache miss. Common origin types:

  • S3 bucket — for static sites and assets.
  • HTTP server — any public web server, including EC2 or an Application Load Balancer.
  • AWS Lambda function URL — serverless backend.
  • MediaStore / MediaPackage — for video streaming.

A distribution can have multiple origins and route requests to them based on the URL path. For example, /api/* could go to an ALB while everything else goes to S3.

Cache behaviors

A behavior is a rule that maps a path pattern to an origin and decides how requests are cached. Every distribution has a default behavior (path pattern *) and zero or more ordered behaviors that are checked first.

Behaviors control:

  • Viewer protocol policy — redirect HTTP to HTTPS, allow both, or HTTPS only.
  • Allowed methodsGET, HEAD, or include POST, PUT, DELETE for APIs.
  • Cache policy — what gets included in the cache key (headers, query strings, cookies) and the TTL range.
  • Origin request policy — which headers and query strings are forwarded to the origin.
  • Response headers policy — security headers like HSTS or CSP added to responses.

A reasonable starting point for a static site:

Default behavior (*)
  Origin: my-site-bucket.s3.us-east-1.amazonaws.com
  Viewer protocol policy: Redirect HTTP to HTTPS
  Allowed methods: GET, HEAD
  Cache policy: CachingOptimized (managed)
  Compress objects: Yes

Behavior /api/*
  Origin: api.example.com (ALB)
  Allowed methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
  Cache policy: CachingDisabled (managed)
  Origin request policy: AllViewer

TTLs and the cache key

CloudFront uses the cache key to decide whether a request can be served from cache. By default, the key includes the host, the path, and anything the cache policy adds — headers, cookies, or query strings.

TTL works in three layers:

  • Object TTL — set by the Cache-Control header on the origin response.
  • Minimum / default / maximum TTL in the cache policy — clamps the object TTL.
  • Stale-while-revalidate behavior when origins are unreachable, depending on configuration.

For a static site, ship sensible Cache-Control headers from S3 metadata: long max-ages for hashed assets like app.abc123.js, short or no-cache for index.html.

Invalidations

When you deploy a new version and the cached object has a long TTL, you have two options:

  1. Change the URL (cache-busting via hashed filenames).
  2. Submit an invalidation to mark cached copies stale immediately.

Hashed filenames are the cheaper and faster pattern for assets — CloudFront does not need to do anything because the URL changed. For HTML files that have stable URLs, invalidations are the right tool:

aws cloudfront create-invalidation \
  --distribution-id E1ABC23DEF456G \
  --paths "/index.html" "/blog/*"

The first 1,000 invalidation paths per month are free; after that, AWS charges per path. Avoid the temptation to invalidate /* on every deploy — design your Cache-Control headers so you do not need to.

Pairing with S3

The S3 + CloudFront combination powers an enormous fraction of the web’s static sites. The recommended modern setup:

  1. Create a private S3 bucket. Do not enable static website hosting; do not set the bucket public.
  2. Create a CloudFront distribution with the bucket as origin.
  3. Use Origin Access Control (OAC) so only CloudFront can read from the bucket.
  4. Add a bucket policy that allows the CloudFront service principal to s3:GetObject.

The bucket policy looks like:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "cloudfront.amazonaws.com" },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-site-bucket/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1ABC23DEF456G"
        }
      }
    }
  ]
}

This pattern keeps the bucket private end to end. The origin URL is not directly reachable; users only ever hit CloudFront.

Signed URLs and signed cookies

For private content — paid downloads, gated documents, video catalogs — you need to serve files through CloudFront but only to authorized users. Signed URLs and signed cookies solve this.

A signed URL is a normal CloudFront URL with extra query parameters that prove the request was authorized by a holder of your private key. The signature can encode an expiration time and an IP range.

Typical flow:

  1. Set up a CloudFront key group containing a public key.
  2. In your application, hold the matching private key in a secure store (Secrets Manager or KMS).
  3. When a logged-in user requests content, your app generates a signed URL pointing at CloudFront.
  4. The browser fetches that URL; CloudFront verifies the signature and serves the object.

Signed cookies do the same thing but cover entire path prefixes, which is friendlier for HLS video manifests that pull dozens of segments.

Logging and metrics

CloudFront publishes:

  • Standard logs delivered to an S3 bucket for analysis with Athena.
  • Real-time logs streamed to Kinesis Data Streams for live dashboards.
  • CloudWatch metrics — requests, bytes, error rates, cache hit ratio.

The single most useful metric is cache hit ratio. If it is low (under 80% for static content), revisit your cache key and Cache-Control headers — almost every misconfiguration shows up here first.

Wrap up

CloudFront is more than a CDN bolted onto S3; it is a programmable edge layer with cache behaviors, security headers, and signed access controls. Start simple — one origin, one default behavior, sane Cache-Control headers — and add behaviors only when a real path needs different treatment.

Once you have a distribution working, the next steps are usually wiring it into Route 53, terminating a custom HTTPS certificate via ACM, and pushing security headers from a response headers policy. Combined with the S3 backend covered in S3 basics, you have a fast, durable, and inexpensive way to serve content globally.