Cloud platforms · AWS

Static website on S3, CloudFront, WAF and Route 53

The default for marketing sites, documentation and public information: a private S3 origin behind CloudFront with WAF, managed TLS and a pipeline that deploys with short-lived credentials.

A reference architecture from EITSAA, not a named client system. Service limits, prices and product features change, so confirm current details before you commit to a design.

  • WCAG 2.2 AA (content)
  • ACSC Essential Eight
  • Australian Privacy Principles (APP 11)
  • Sydney (ap-southeast-2) origin

Architecture

Architecture diagram. Tinted boundaries show regions, accounts, networks and trust zones. Numbered arrows match the flow below.
Static website on S3, CloudFront, WAF and Route 53 architectureVisitor to Route 53: DNS. Visitor to CloudFront: HTTPS 443. CloudFront to AWS WAF: inspect. CloudFront to S3 origin bucket: OAC, SigV4. CloudFront to S3 log bucket: logs. ACM certificate to CloudFront: cert. GitHub Actions to S3 origin bucket: OIDC deployInternetAWS account · origin in ap-southeast-2 · WAF andcertificate in us-east-1GitHubVisitorBrowser or crawlerRoute 53Alias A/AAAA recordsCloudFrontTLS 1.2+, HTTP/3, cacheACM certificateAuto-renewing, us-east-1AWS WAFManaged rules, rate limitS3 origin bucketPrivate, OAC onlyS3 log bucketAccess logs, lifecycleGitHub ActionsBuild, test, deploy1DNS2HTTPS 4433inspect4OAC, SigV45logscert6OIDC deployPlatform servicesAWS IAMAmazonCloudWatchAWS CloudTrailAWS KMS
  • People and clients
  • Network and edge
  • Security and identity
  • Object and file storage
  • Delivery tooling
  • Monitoring, audit and analytics
  • Request or data flow
  • Asynchronous or optional
  • Boundary: region, account, network or trust zone

Request and data flow

  1. The browser resolves the domain. Route 53 returns an alias to the CloudFront distribution, so the apex domain works without a CNAME.

  2. The browser connects to the nearest CloudFront edge over TLS 1.2 or newer. HTTP is redirected to HTTPS and a response headers policy adds HSTS, CSP and the other security headers.

  3. The web ACL evaluates the request first: AWS managed rule groups, an IP reputation list and a rate-based rule. Blocked requests never reach the origin.

  4. On a cache miss CloudFront fetches the object from S3 using origin access control, which signs requests with SigV4. The bucket policy only trusts this one distribution.

  5. Standard access logs land in a separate bucket with a lifecycle rule, ready for Athena queries or a SIEM.

  6. A GitHub Actions workflow assumes a deploy role through OIDC, syncs the build to S3, sets cache headers and creates a targeted invalidation. No long-lived access keys exist.

Components and why they were chosen

ComponentWhat it doesWhy this choice
Amazon S3 (private bucket)Holds the built site. Block Public Access is on at account and bucket level.S3 gives very high durability and no servers to patch. A public website endpoint is avoided because it cannot use OAC.
Amazon CloudFrontGlobal cache, TLS termination, HTTP/3, compression, redirects and security headers.Offloads almost all traffic from the origin and gives one place to attach WAF, logging and headers.
Origin access control (OAC)Signs CloudFront-to-S3 requests so only the distribution can read the bucket.OAC replaces the legacy origin access identity and supports SSE-KMS and all S3 Regions.
AWS WAF web ACLManaged rule groups, rate-based rules and optional geo or bot controls.Cheap protection for a public endpoint. A CloudFront web ACL has to be created in us-east-1.
AWS Certificate ManagerIssues and renews the public TLS certificate.Free for use with CloudFront and removes expiry incidents. The certificate must be in us-east-1.
Amazon Route 53Public hosted zone with alias records to CloudFront, plus DNSSEC if required.Alias records are free to query and work at the zone apex.
IAM role with GitHub OIDCShort-lived credentials for the pipeline, scoped to one bucket and one distribution.Removes stored secrets, which is the usual cause of leaked deploy keys.

Design decisions and trade-offs

Origin type

Private S3 bucket with OAC, no website endpoint.

Why. Keeps the bucket unreachable except through CloudFront, so WAF and headers cannot be bypassed.

Trade-off. Directory index and clean URLs need a small CloudFront Function or build-time paths, because S3 REST endpoints do not resolve /about/ to index.html.

Hosting model

Static export on S3 rather than Amplify Hosting or a server.

Why. Lowest cost and attack surface, predictable performance, and any CI system can deploy it.

Trade-off. Dynamic features move to separate APIs or third-party forms. Preview environments need extra pipeline work.

Cache policy

Long immutable caching for hashed assets, short caching for HTML, targeted invalidations.

Why. Hashed filenames make stale assets impossible and keep invalidation cost near zero.

Trade-off. HTML is cached briefly, so urgent content fixes need an invalidation step in the pipeline.

Security headers

CloudFront response headers policy rather than Lambda@Edge.

Why. Managed feature with no code to run, patch or bill per invocation.

Trade-off. A strict CSP with inline scripts needs hashes generated at build time.

Well-architected pillars

Security

Private origin, WAF in front, TLS 1.2 or newer, security headers, no stored credentials and S3 Block Public Access.

Reliability

S3 and CloudFront are regional and global managed services. Versioning on the bucket gives a one-step rollback of a bad deploy.

Performance

Edge caching, Brotli and gzip, HTTP/3 and immutable assets. Time to first byte is edge-served for cache hits.

Cost optimisation

Pay for requests, data transfer and WAF rules. For a typical brochure site the monthly bill is small and driven by transfer and WAF.

Operational excellence

One workflow deploys everything. Infrastructure lives in Terraform or CDK so the distribution is reproducible.

Sustainability

No idle compute, and caching reduces repeat transfers. Image optimisation at build time lowers bytes served.

Network, identity and data

Networking

No VPC is needed. The only public surface is the CloudFront distribution. The bucket policy denies everything except the distribution's service principal with a source ARN condition, and denies non-TLS access.

Identity and least privilege

Two roles only: a deploy role (s3:PutObject and DeleteObject on one bucket, cloudfront:CreateInvalidation on one distribution) trusted by the GitHub repository and branch through OIDC, and a read-only audit role for humans via IAM Identity Center.

Data and encryption

Content is public by design, so classification is OFFICIAL public content. Use SSE-S3 by default, or a customer-managed KMS key if policy requires it. Do not host forms data here. Note that CloudFront caches content at global edge locations, so confidential content does not belong in this pattern.

Security and compliance mapping

ControlHow this design addresses it
Patch applications and operating systemsNo servers or operating systems to patch. Build dependencies are scanned in CI. Essential Eight patch applications, applied to the build chain.
Restrict administrative privilegesNo long-lived keys, deploy role scoped to one bucket and distribution, human access through MFA-backed Identity Center. Essential Eight restrict administrative privileges.
Regular backupsS3 versioning plus the Git repository as the source of truth. Essential Eight regular backups.
Logging and monitoringCloudFront and S3 access logs, CloudTrail for configuration changes. Supports ISMF event logging expectations.
PrivacyAnalytics and forms must be assessed under APP 1 and APP 5 notices. No personal information is stored by this tier.

Mappings show how the design supports each control. They are not certifications, and EITSAA does not claim IRAP assessment or compliance for any reference architecture.

Failure modes, targets and scaling

  • Target RTOMinutes (redeploy or switch origin group)
  • Target RPOZero for content held in Git; seconds for replicated objects
  • Scaling and limitsScales with CloudFront. Check service quotas for distributions per account, WAF rules and invalidation paths per month.
Failure modeMitigation
Bad deploy publishes a broken pageVersioned bucket and an immutable build artefact. Redeploy the last good commit and invalidate. Smoke test in the pipeline before invalidation.
Certificate or DNS mistake causes an outageACM validation records managed in code, CloudFront alternate domain names checked in plan, low TTL during cutovers.
Bot or scraping spikeRate-based WAF rule and bot control if needed. CloudFront absorbs the traffic from cache.
Regional S3 impairmentCached content continues to be served. For stronger resilience add an origin group with a replicated bucket in a second Region.

Observability and runbooks

  • CloudFront metrics (requests, 4xx and 5xx rate, cache hit ratio) with alarms to the on-call channel.
  • WAF sampled requests and blocked counts, reviewed after each campaign launch.
  • Synthetic check from outside AWS for the key pages and the certificate expiry date.
  • Runbook: deploy rollback, invalidation, emergency WAF block rule and DNS failover steps.

Cost drivers and levers

CloudFront data transfer and requests, WAF web ACL and rule fees, Route 53 hosted zone and queries.

  • Choose a price class that matches where your visitors are.
  • Raise the cache hit ratio with longer TTLs for hashed assets.
  • Compress and resize images at build time.
  • Expire log objects after 90 to 400 days depending on retention policy.

Implementation and fit

Phased approach

  1. Week 1: Terraform or CDK for bucket, distribution, ACM and WAF in a non-production account.
  2. Week 2: pipeline with OIDC, smoke tests and cache rules; performance and accessibility gates.
  3. Cutover: lower DNS TTL, validate certificates, switch the alias record, monitor for 48 hours.
  4. After go-live: tune WAF rules from real traffic and add the second-Region origin only if the business case exists.

Anti-patterns to avoid

  • Making the bucket public and using the S3 website endpoint.
  • Committing access keys to the repository or CI secrets.
  • Invalidating /* on every deploy.
  • Putting forms or personal data handling inside the static tier.

When to use it

  • Public marketing, information and documentation sites.
  • Sites that change by publishing, not by user interaction.
  • Teams that want low running cost and a tiny attack surface.

When not to

  • Content that must stay inside Australia at the edge too.
  • Authenticated or personalised pages (use an application tier).
  • Large editorial teams that need a live CMS preview without a headless CMS.

More in cloud platforms

Related insights

Discuss this architecture

Tell us your systems, constraints and timeline. We reply within one business day, and the initial conversation is free.