How a request
finds you
You type a domain and the page is there before you finish blinking. Twenty-six stops on what happens in between — and at the end, proof that this deck itself made the trip.
Three questions, in order
Every page load answers them one after another. Lose any one and nothing loads.
Nobody knows the whole answer
DNS is a chain of referrals. Each server knows only who to ask next, until one is authoritative for the name.
Route 53 does three separate jobs
Billed separately, configured separately, and conflated constantly.
Sells you the name
Domain registration. The only part you could buy elsewhere and still use everything below.
Answers for the name
Authoritative DNS. A hosted zone holds your records, and four assigned name servers serve them worldwide.
Watches your endpoints
Health checks. Route 53 is the rare DNS service that changes its answers based on whether a target is still alive.
That third job is the interesting one. It turns DNS from a lookup table into a control plane, which is what makes failover and latency routing possible at all.
Registrar and DNS are two different jobs
The domain is registered at Hostinger. The records will live in Route 53. You delegate, rather than transfer.
Public hosted zone
Answers anyone on the internet. This is what asimisinthe.cloud needs.
Private hosted zone
Answers only from inside the VPCs you associate with it. Same records, invisible from outside.
A hosted zone is just a file
Records map a name to a value, plus a type telling the resolver how to read that value.
NS and SOA arrive with the zone
Delete them and the zone stops answering. A surprisingly common self-inflicted outage.
Type decides where the lookup ends
A and AAAA finish with an address. CNAME and ALIAS send the resolver on one more hop.
TTL is how long you lose control
Resolvers cache your answer for exactly as long as you told them to. Nothing you change at AWS shortens that.
Long TTL is fast and cheap. Short TTL is agile. Before a planned cutover, drop the TTL to 60 seconds a day ahead, migrate, then put it back.
The reason this deck needs Alias
A CNAME cannot exist at the root of a domain. The spec forbids it, and the root is exactly where you want your site.
CNAME at the apex — rejected
asimisinthe.cloud → d1x2y3.cloudfront.net
The apex already holds NS and SOA records. A CNAME has to be the only record at its name, so the two can't coexist. Route 53 refuses to save it.
Alias at the apex — works
asimisinthe.cloud ⇒ d1x2y3.cloudfront.net
Alias is Route 53's own extension. It resolves the target internally and hands back plain A records, so the apex never sees a CNAME. Free to query, and it follows the target's IPs as they change.
Alias only points at AWS targets — CloudFront, ALB, S3 website endpoints, or another record in the same zone. For anything else you still need a CNAME on a subdomain.
One name, many answers
A routing policy decides which record Route 53 hands back. Same question, different answer depending on who is asking. Try them.
One record, one answer, for everyone. No health awareness and no geography — the default, and still the right choice most of the time.
Four more, by intent
The rest differ in what they optimise for, not in how they work.
Geolocation
Answers by where the viewer is — continent, country, or US state. For language, licensing and legal boundaries. Always set a default record, or viewers you didn't anticipate get nothing at all.
Geoproximity
Answers by distance to your resources, with a bias dial that grows or shrinks a region's catchment area. The only policy that needs traffic flow to configure.
Multi-value
Returns up to eight healthy records at once and lets the client choose. Health-aware round robin — not a load balancer, but far better than nothing.
IP-based
Answers by the viewer's CIDR block. For when you know a particular ISP's users should land somewhere particular.
The distinction people miss: latency optimises for speed and will happily send a Dublin viewer to Virginia if that path is faster today. Geolocation optimises for location and never will.
Failover needs someone watching
Health checkers around the world request your endpoint on a schedule. Fail enough of them and Route 53 stops handing out that record.
A health check can watch an endpoint, watch other health checks, or watch a CloudWatch alarm. Only the first one costs you an HTTP request.
Distance is the slowest part of your stack
You can take a query from 40 ms to 4 ms. You cannot negotiate with the speed of light between Karachi and Virginia.
A CDN does not make your origin faster. It moves the origin out of the request's way — which turns out to be the same thing.
What a distribution actually is
A global fleet of caches, plus rules describing where to fetch from and what to keep.
The regional layer is why a cold edge is rarely as slow as it sounds. A miss usually resolves one hop away rather than all the way home.
A cache hit never reaches your origin
The same request, measured two ways.
The cache key decides everything
CloudFront hashes parts of the request into a key. Add a part and you split the cache — every extra value is another copy to fill and another miss to pay for.
asimisinthe.cloud/index.html
Objects now cached
1
One object, shared by every viewer on earth. This is the hit rate you want.
The rule
Include something in the key only if the response genuinely changes because of it. A cookie your origin ignores turns one cached object into one object per user, and your hit rate into a rounding error.
Two policies, one shared vocabulary
A cache policy chooses what goes into the cache key — and those parts get forwarded too. An origin request policy forwards things without putting them in the key. That difference is the whole point of having two.
allViewer · allViewerAndWhitelistCloudFront
Why headers have no "all" in a cache policy
Putting every viewer header in the key would give almost every request its own object — User-Agent
alone would shatter it. AWS removed the foot-gun: forward all headers with an origin request policy instead,
and keep them out of the key.
The pattern you'll actually use
Cache policy keeps the key narrow. Origin request policy hands the origin what it needs to do its job —
CloudFront-Viewer-Country, User-Agent, an auth cookie — none of which should split
the cache.
Four filters, one grammar
Query strings, cookies and headers each take the same four settings, in both policies. Most of debugging a bad hit rate is working out which one you picked.
None
Strips them out. Nothing reaches the key, nothing reaches the origin. The default, and exactly right for a static site that ignores them anyway.
Whitelist
Name the items that may pass; everything else is dropped. The console calls it include specified. Reach for this one first — it is the only option whose blast radius you can see.
AllExcept
Everything passes but the ones you name. Its real use is dropping the noise — utm_source and
friends, which never change the response but would each fork the cache.
All
Everything passes. In a cache policy that is a key per unique combination, which is defensible only for a path you have already decided not to cache.
The same four words carry a different consequence in each policy. In a cache policy the choice sets your hit rate. In an origin request policy it only sets how much your origin gets told — costly to your backend, free to your cache.
Two ways to stop serving stale bytes
Wait for the TTL, or force the issue. One is free and slow; the other is immediate and metered.
Let the TTL expire
The origin's Cache-Control header sets it; the cache policy's min, default and max TTL clamp it.
Costs nothing, but you wait.
Invalidate the path
Evicts matching objects from every edge within minutes. A generous number of paths are free each month, and billed after that — so version your filenames instead of invalidating on every deploy.
One distribution, different rules per path
Cache behaviours match the URL path and decide the origin, the cache policy, the allowed methods, and whether the response is cached at all.
Precedence is by the order you list them, not by specificity. Put a broad pattern above a narrow one and the narrow one never runs.
Lock the origin so only the edge can reach it
A public bucket behind a CDN is still a public bucket. Origin access control signs CloudFront's requests so the bucket can refuse everyone else.
The same distribution can hold an ALB or EC2 origin alongside it, where CloudFront gives you TLS termination, header manipulation and shielding rather than caching. Shutting that door works nothing like this one.
When the origin is compute, not a bucket
A bucket has OAC. An ALB or an EC2 instance has a security group — which for years meant the origin had to sit on the public internet and hope the allowlist held.
The question to ask of any origin is simply whether it is reachable without CloudFront. A public ALB is — the prefix list narrows the crowd but the door still faces the street. A VPC origin has no door on that side of the building, which is what OAC does for a bucket.
Three levers, three different questions
Geo restriction
Allow or block whole countries at the edge, using CloudFront's own GeoIP lookup. The request is refused before it reaches your origin. For licensing and compliance, not for security.
Signed URLs
One signed link per file, carrying an expiry and optionally an IP range. Right for a single download — a purchased video, a report, a firmware image.
Signed cookies
One signature covering many files. Right for a whole library behind a paywall, where minting a URL per asset would be absurd.
Both signature types verify against a key group — public keys you upload to CloudFront, with the private key held by whatever service issues the signatures. The root account key pair is the legacy path and no longer the recommended one.
Who holds which key
Signing and verifying happen in two different places, run by two different parties, at two different times. Almost every mistake here is a confusion about which is which.
CloudFront never learns who your subscribers are, and your database is never consulted at request time. The signature is the whole handoff between the two.
Two signatures that sound alike and aren't
Both hand someone a temporary link. They are signed by different things, land in different places, and can do different amounts of damage.
CloudFront signed URL
Signed by a private key whose public half sits in a key group. Verified at the edge, so the object stays cached and still arrives from the nearest location.
Can front any origin, not only S3. Read access only. The policy can pin an expiry, a start time, and a source IP range.
S3 pre-signed URL
Signed by the IAM credentials of whoever generated it, and inherits exactly that identity's permissions — which is the part that surprises people.
Points straight at the bucket, bypassing the edge entirely. Can grant writes as well as reads, so a leaked one may let a stranger upload.
If the content is meant to be distributed, sign it at CloudFront. A pre-signed URL in front of a private bucket you have already locked with OAC will simply be refused — the two mechanisms are answering different questions.
Every piece, one request
You have been looking at it for twenty minutes
This deck is a static site in S3, private, served through CloudFront, reached by an alias record at the apex. Open the network tab.
Then: edit one word, aws s3 sync, reload — still the old copy.
Invalidate, reload — new copy, and the header flips back to a miss.
Three things that will bite you
The certificate must be in us-east-1. CloudFront reads ACM only from that region, no matter where anything else lives.
Use alias, not CNAME, at the apex. The subdomain works either way, which is why people only discover this at the root.
Distributions deploy slowly. Certificate validation and propagation take real minutes — never do them live in front of an audience.