CloudFront
After this you can answer: What does CloudFront add in front of the load balancer, and how does the load balancer trust it?
Picture it
Section titled “Picture it”flowchart TB B[Browser] -->|"HTTPS"| CF["CloudFront edge"] CF -->|"HTTP 80 + X-Origin-Verify"| ALB["ALB :80"] ALB -->|"rule 100: header + /trpc/*"| A["api"] ALB -->|"rule 200: header"| W["web"] ALB -.->|"no header: 403"| X["refused"]How it works
Section titled “How it works”- Edge. The browser talks HTTPS to CloudFront, using the free
*.cloudfront.netcertificate. - Cache.
/_next/static/*(hashed JS and CSS) is cached at the edge./trpc/*and the pages are not cached. - The security group filters source IPs.
alb-sgallows TCP 80 only from the AWS managed prefix list for CloudFront. But every CloudFront distribution, including other people’s, uses those ranges. - The header identifies this distribution. CloudFront adds
X-Origin-Verifywith a random value. The ALB’s listener forwards only requests that carry it; its default action is a fixed 403.
In MiniTickets
Section titled “In MiniTickets”The distribution is made in infra/src/entry/cdn.ts → createCdn, the HTTP
listener with the header rules in infra/src/entry/listener.ts → createListener,
and the header value in infra/src/entry/origin-secret.ts → createOriginSecret:
32 random letters and digits, because the ALB reads * and ? in a header condition as wildcards.
Why it is off: a new AWS account may need verification by AWS Support before it can create
CloudFront distributions. Until then, MiniTickets runs in ALB-only mode: the ALB serves HTTPS
directly with the ACM certificate. Switching modes is done only while entryEnabled is false,
because both modes have a listener on port 80.
The web app sends private, no-store on every HTML page, so CloudFront would store no page, even
/events.
| From → to | What happens | What allows it |
|---|---|---|
| Browser → CloudFront distributiononly when cdnEnabled = true | HTTPS to the nearest edge location, https://<id>.cloudfront.net |
|
| CloudFront distribution → Application Load Balanceronly when cdnEnabled = true | fetches from the origin over plain HTTP on port 80, adding the X-Origin-Verify header |
|
| Origin secret → CloudFront distributiononly when cdnEnabled = true | CloudFront sends this value as X-Origin-Verify |
|
See it in AWS
Section titled “See it in AWS”CloudFront → Distributions → comment “minitickets dev: HTTPS in front of the ALB” → Behaviors, Origins. In ALB-only mode there is none.
aws cloudfront list-distributions --query "DistributionList.Items[].{Id:Id,Comment:Comment}"
Break it
Section titled “Break it”| Symptom | Cause | Where to look |
|---|---|---|
| CloudFront returns 504 for every page | alb-sg has no TCP 80 rule for the CloudFront prefix list | alb-sg → Inbound rules |
| The ALB’s own DNS name returns 403 | By design: no secret header | Listener → default action |
| Creating the distribution fails | The account must be verified first | The deploy log (Pulumi error) |
Say it in an interview
Section titled “Say it in an interview”Follow-ups
Section titled “Follow-ups”Why is the security group alone not enough?
The prefix list says “some CloudFront distribution”. Anyone can create one and point it at our ALB. The header proves it is ours.
What is the risk of caching pages at the edge?
A page with one user’s data could be served to another user if the cookie is not part of the cache
key. That is why /trpc/* and pages use CachingDisabled and the web app sends no-store.
What changes for the API when CloudFront is on?
One more proxy stands in front, so the trusted proxy hop count changes. The API must read the real client IP from the right place for rate limits.
Advanced: Behaviors and the hop count
/_next/static/* uses the managed CachingOptimized policy; /trpc/* and the default use
CachingDisabled. PriceClass_100 keeps edge locations to the cheaper regions. TRUST_PROXY_HOPS is
chosen by the mode in infra/src/entry/mode.ts (1 in ALB-only mode). Comments in
infra/src/entry/cdn.ts still describe a 30 s /events cache from before the no-store change;
the code wins.
Checkpoint
Section titled “Checkpoint”Answer these without scrolling up. If one feels hard, reread that section.
- What does CloudFront cache for MiniTickets, and what not?
- What are the two locks, and why are both needed?
- What does the ALB answer to a request without the header?
- Why is CloudFront switched off today?
- Why may the header value contain only letters and digits?
Redraw it from memory: browser → CloudFront → ALB :80 with the header, the two rules, and the 403 default
Try this: on the map, turn on 'Show later stages', find the three dashed CloudFront-mode pieces and read why they are off
Read this book online: https://book.theversehub.in/