CloudFront CDN

how static assets are cached and invalidated

🌐 CloudFront Overview

The frontend application does not read its static assets (ML model weights, 3D .glb models, precomputed data) directly from S3. Instead, they are served through an Amazon CloudFront distribution that sits in front of the artifacts S3 bucket.

  • Distribution ID: E3V0XRM5MEK3WZ
  • Origin: igaawi-prod-api-backend-bucket (S3)
  • Alternate domain (CNAME): cdn.wiperinstall.rainx.com
  • Status: Enabled, Standard distribution

The frontend picks up the CDN URL from the igaawi-prod-frontend secret in AWS Secrets Manager as vite_files_base_url:

vite_files_base_url = https://cdn.wiperinstall.rainx.com

That value is injected into the Vite build at runtime, so the browser fetches every artifact from CloudFront β€” not from S3 directly.

πŸ” Request Flow

graph LR;
    A[Browser] --> B[cdn.wiperinstall.rainx.com]
    B --> C{CloudFront edge}
    C -- cache hit --> A
    C -- cache miss --> D[(S3: igaawi-prod-api-backend-bucket)]
    D --> C
    C --> A
  1. The frontend requests an asset from https://cdn.wiperinstall.rainx.com/....
  2. CloudFront serves it from the nearest edge cache when available.
  3. On a cache miss, CloudFront fetches the object from the S3 origin, stores it at the edge, and returns it to the client.
  4. Because objects are uploaded with Content-Encoding: gzip, CloudFront and the browser handle decompression transparently β€” see Artifacts Storage for details on how the objects are produced.

♻️ Cache Invalidation

Static assets are meant to be long-lived at the edge β€” that is the whole point of using a CDN. However, when igaawi-artifacts pushes new versions of the files to S3, cached copies at CloudFront edges would still serve the old content until TTL expiration.

To avoid stale data after every artifacts refresh, the Sync Bucket GitHub Actions workflow performs a full invalidation as its final step:

aws cloudfront create-invalidation \
  --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" \
  --paths "/*"

This means:

  • Every run of the artifacts sync workflow (for the production environment) invalidates the entire distribution (/*).
  • Clients will see the new artifacts on their next request β€” no manual cache busting or versioned filenames required.
  • Non-production environments (development, staging) do not invalidate β€” the cloudfront_distribution_id input is passed as an empty string and the invalidation step is skipped by an if: condition.

πŸ” IAM Access

The GitHub Actions role provisioned for igaawi-artifacts is granted the minimum required CloudFront permissions, and only for this specific distribution:

{
  actions = [
    "cloudfront:CreateInvalidation",
    "cloudfront:GetInvalidation",
    "cloudfront:ListInvalidations"
  ]
  resources = [
    "arn:aws:cloudfront::187528943262:distribution/E3V0XRM5MEK3WZ"
  ]
}

Full policy is defined in envs/prod/platforms/github/actions/prod.tfvars; see Artifacts Storage for the S3 side of the same role.

  • Artifacts Storage β€” repository, workflow, and S3 layout behind this CDN.
  • DNS β€” how cdn.wiperinstall.rainx.com is resolved to CloudFront.