Skip to main content

Command Palette

Search for a command to run...

AWS S3 + CloudFront Cost Optimization: Simple Guide + Terraform Hands-On

Published
β€’3 min read

Learn how to optimize static website costs and deploy S3 + CloudFront with Terraform

Why S3 + CloudFront?

S3 + CloudFront is one of the simplest ways to host a fast, secure static website on AWS.
S3 stores your files, and CloudFront distributes them globally with caching.

You pay mostly for:

  • storage (S3)

  • requests

  • data transfer out (CloudFront)

For many front-end apps, this setup is cheaper and easier to operate than servers.

Cost Optimization: the real levers

S3 + CloudFront costs depend on a few practical levers:

  • Cache hit ratio: more cache hits = fewer origin requests = lower cost.

  • Data transfer out: large assets and video increase spend quickly.

  • Invalidations: frequent full-cache invalidations can add cost after free tier limits.

  • File strategy: immutable hashed assets (assets/app.abc123.js) reduce re-downloads.

  • Price class: CloudFront PriceClass_100 can reduce cost if global ultra-low latency is not required.

Quick tip: keep index.html short-cache/no-cache, and static assets long-cache + immutable.

Advantages of S3 + CloudFront

  • βœ… Low ops overhead (fully managed)

  • βœ… Good performance worldwide

  • βœ… Secure private S3 origin with OAC

  • βœ… Scales automatically

  • βœ… Great fit for React/Vue static builds

When to use S3 + CloudFront

Great fit for:

  • Static front-end apps (React/Vue/Angular build output)

  • Marketing sites and documentation portals

  • SPAs with client-side routing

  • Workloads with variable global traffic

When NOT to use S3 + CloudFront

Avoid this architecture if:

  • ❌ You need server-side business logic (without adding Lambda/API backend)

  • ❌ You need dynamic rendering tightly coupled to each request

  • ❌ You need WebSocket-heavy real-time backend features

Hands-on with Terraform (simple)

This repo already includes a modular S3 + CloudFront stack:

  • private S3 bucket

  • CloudFront distribution

  • Origin Access Control (OAC)

  • bucket policy for CloudFront-only access

  • static file upload from react-app/dist

  • CloudFront invalidation after deploy

πŸ“¦ Source Code

Get the complete code here: serverless-stack on GitHub

git clone https://github.com/Ankoay-Feno/serverless-stack.git
cd serverless-stack

Prerequisites

  • AWS account

  • AWS CLI configured

  • Terraform >= 1.5

  • Node.js + npm

Step 1: Configure AWS CLI

aws configure

Step 2: Build the React app

cd s3+cloudfront/react-app
npm install
npm run build

Step 3: Prepare Terraform variables (optional)

cd ../terraform
cp terraform.tfvars.example terraform.tfvars

Edit if needed:

  • aws_region

  • app_name

  • environment

  • price_class

  • build_dir

Step 4: Initialize Terraform

terraform init

Step 5: Plan and apply

terraform plan
terraform apply

Terraform will:

  • create a private S3 bucket

  • create CloudFront + OAC

  • upload static files

  • invalidate CloudFront cache after deployment

Step 6: Open the website

After apply:

terraform output website_url

You can also check:

  • terraform output cloudfront_domain_name

  • terraform output bucket_name

Clean up

To remove all resources:

terraform destroy

Conclusion

S3 + CloudFront is a strong default for static websites: simple, scalable, and cost-efficient.
To optimize cost, focus on cache strategy, asset sizing, and invalidation discipline.

πŸš€ Next Steps

If you want, I can also add:

  • Custom domain + HTTPS (ACM + Route53)

  • CI/CD deployment (GitHub Actions)

  • Monitoring dashboard (CloudWatch + billing alarms)

Found this helpful? Don't forget to star the GitHub repo and share with your team.