Skip to content

Edge & DNS

Get any of these wrong and the failure is quiet until it isn't: a TTL left too high turns a "five-second failover" into ten minutes of an outage nobody can explain, a forgotten cache invalidation serves last week's price list to paying customers, and a GWLB where a plain ALB would do inspects traffic it was never built to see. Each traces back to the same three questions: what decides which DNS record wins, what a cache actually does on a miss, and which OSI layer a load balancer needs to understand.

Scope: the AWS module page introduced Route 53, CloudFront, and Global Accelerator as "the traffic-arrival story," and a one-line table of ALB/NLB/GWLB. This page goes one layer deeper: how Route 53 actually resolves and fails traffic over, what CloudFront caching really does on a miss vs a hit, when Global Accelerator earns its keep over CloudFront, and a full decision table for the three load balancers.

TL;DR — in 30 seconds:

  • An Alias record can sit at the zone apex where a CNAME legally can't — that's why Route 53 points Alias records at CloudFront/ALB/S3 instead of using a CNAME.
  • CloudFront trades a cache miss now for a fast edge hit later; Global Accelerator skips caching entirely and just routes non-cacheable, latency-sensitive traffic over the AWS backbone.
  • Pick ALB when you need to route by request content (host/path), NLB for raw throughput or a static IP, and GWLB only when threading traffic through an inline third-party appliance.

1. Route 53 — zones, records, and routing policies

A hosted zone is a container for the DNS records of one domain. Every record in it has a type (what kind of answer it returns) and a routing policy (which record Route 53 hands back when there's more than one candidate).

  • Alias records are a Route 53-only extension of the standard A/AAAA record. They point at an AWS resource (a CloudFront distribution, an ALB, an S3 website endpoint) instead of an IP, and — unlike a CNAME — an Alias record can sit at the zone apex (example.com, not just www.example.com), because the DNS standard forbids a CNAME from coexisting with any other record type at the apex.
  • Routing policies decide which record wins when several could answer: Simple (one record, no logic), Weighted (split traffic by percentage — canary releases), Latency-based (route to the region with the lowest measured latency for that resolver), Geolocation (route by the requester's location), and Failover (primary/secondary, gated by a health check).

Health-check-driven failover is where Route 53 stops being "just DNS" and starts being part of your availability story: a health check polls an endpoint (HTTP, HTTPS, or TCP) on an interval, and a Failover routing policy only returns the primary record while its health check is passing. When it fails, Route 53 starts answering with the secondary record instead — no code deploy, no manual cutover.

sequenceDiagram
    participant C as Client
    participant R53 as Route 53
    participant HC as Health check
    participant P as Primary endpoint
    participant S as Secondary endpoint

    HC->>P: poll every N seconds
    P-->>HC: healthy
    C->>R53: resolve example.com
    R53-->>C: primary IP (health check passing)

    Note over P: primary starts failing
    HC->>P: poll
    P--xHC: unhealthy
    R53->>R53: failover policy flips answer

    C->>R53: resolve example.com
    R53-->>C: secondary IP (automatic failover)

DNS answers are cached by resolvers for the record's TTL — a low TTL makes failover propagate faster at the cost of more queries against the hosted zone; a high TTL is cheaper but slower to fail over. This is a real trade-off to set deliberately, not a default to leave alone on anything you plan to fail over.

2. CloudFront — caching at the edge

CloudFront is a CDN: a global network of edge locations that cache responses from an origin (an S3 bucket, an ALB, any HTTP endpoint) close to the requester, so most requests never have to travel back to the origin at all.

  • On a cache hit, the edge location answers directly — this is the fast path, and the entire point of putting a CDN in front of an origin.
  • On a cache miss, the edge location fetches from the origin, serves the response, and stores a copy for the next request — so the second request for the same object is a hit.
  • What gets cached and for how long is controlled by a cache behavior: a path-pattern-matched rule that sets the TTL, which headers/cookies/query strings vary the cached object, and which origin serves that path. A distribution can route /api/* to one origin with caching disabled and /static/* to another with a long TTL, in the same distribution.
  • Stale content is cleared with an invalidation (evict specific paths immediately) or by versioning the object's URL (e.g. a content hash in the filename) so the old cached copy is simply never requested again — versioning is the cheaper, more scalable pattern at high traffic. (Go deeper: the official CloudFront invalidation guide — optional, not required to defend this page.)

3. Global Accelerator — when caching isn't the answer

Global Accelerator solves a different problem than CloudFront. It doesn't cache anything — it gives you two static anycast IP addresses and then routes each request over the AWS global backbone network to the closest healthy endpoint, instead of over the public internet's unpredictable path.

Reach for CloudFront when the workload is cacheable (static assets, API responses that don't change per-request) — the win is not making the trip at all. Reach for Global Accelerator when the workload is not cacheable (a UDP-based game server, a gRPC or WebSocket connection, a TCP endpoint) but still needs consistently low latency and fast regional failover — the win is making every trip faster and more reliable, not skipping it.

4. Choosing a load balancer — ALB vs NLB vs GWLB

All three sit on a route table's 0.0.0.0/0 row for inbound traffic and distribute it across a target group — the difference is which OSI layer each one understands.

flowchart TD
    Q1{"Traffic routes through a<br/>third-party virtual appliance<br/>(firewall / IDS) inline?"}
    Q1 -->|"yes"| GWLB["GWLB"]
    Q1 -->|"no"| Q2{"Routing decision needs to<br/>look inside the request<br/>(host header / URL path)?"}
    Q2 -->|"yes"| ALB["ALB"]
    Q2 -->|"no"| NLB["NLB<br/>(raw throughput, static IP,<br/>or not HTTP at all)"]
ALB NLB GWLB
OSI layer L7 (HTTP/HTTPS) L4 (TCP/UDP) L3 (IP)
Routes by host header, URL path, headers connection (IP + port) — passes traffic through, doesn't route by content
Throughput moderate — pays a cost to inspect content extreme — millions of requests/sec, sub-ms latency matched to the appliance behind it
Static IP no (DNS name only) yes, one per AZ — (uses GENEVE encapsulation to the appliance)
Preserves source IP no by default (adds X-Forwarded-For) yes yes
Typical use web apps, microservices routed by path/host gaming, IoT, extreme throughput, needs a static IP (e.g. allow-listing) inline security appliances — firewalls, intrusion detection

Pick ALB whenever the routing decision needs to look inside the request (which service owns /checkout vs /search). Pick NLB whenever the workload needs raw throughput, a static IP a client can allow-list, or isn't HTTP at all. Pick GWLB only when you're threading traffic through a third-party virtual appliance (a firewall, an IDS/IPS) that every packet must pass through inline before it reaches its real destination — it's the odd one out because it isn't balancing traffic to your application at all, it's balancing traffic to a fleet of appliances that inspect it.

flowchart LR
    Client(("Client"))
    subgraph L7["ALB — Layer 7"]
      direction TB
      Rule1["/checkout/* → checkout service"]
      Rule2["/search/*  → search service"]
    end
    subgraph L4["NLB — Layer 4"]
      direction TB
      Conn["raw TCP/UDP,<br/>static IP per AZ"]
    end
    subgraph L3["GWLB — Layer 3"]
      direction TB
      Appliance["inline virtual appliance<br/>(firewall / IDS)"]
    end
    Client --> L7
    Client --> L4
    Client -->|"through the appliance,<br/>then on to its real destination"| L3

5. How this connects

  • This extends the AWS module page's "traffic-arrival story" — Route 53, CloudFront, Global Accelerator, and the ALB/NLB/GWLB table — with the mechanism behind each: how failover actually triggers, what a cache hit/miss really does, and the concrete decision criteria between the three load balancers.
  • The Alias-vs-CNAME distinction and the failover mechanism both come back in the module's Prove gate question about routing a request into the cluster — know the record type as well as the load balancer.

Common gotchas

  • Leaving TTL high on a record you plan to fail over. Fix: a high TTL means resolvers keep answering with the old (dead) record for longer — set a deliberately low TTL on anything with a Failover routing policy.
  • Trying to point a CNAME at the zone apex. Fix: DNS forbids a CNAME from coexisting with any other record at the apex — use an Alias record instead, a Route 53-only extension without that restriction.
  • Forgetting to invalidate or version a changed object behind CloudFront. Fix: without an invalidation or a new (versioned) URL, the edge keeps serving the stale cached copy until its TTL expires — versioning the URL scales better at high traffic than invalidating.
  • Reaching for CloudFront on non-cacheable traffic (a WebSocket, gRPC, raw TCP). Fix: CloudFront's win is skipping the trip on a cache hit — for traffic that can never be cached, Global Accelerator (routes over the AWS backbone) is the tool, not CloudFront.
  • Picking GWLB by default because "it's the third load balancer." Fix: GWLB doesn't balance traffic to your application at all — it threads traffic through an inline third-party appliance (firewall/IDS); reach for ALB or NLB unless that's specifically the need.
Check yourself — you need a static IP a client can allow-list, and the workload isn't HTTP. Which load balancer, and why not ALB?

NLB — it operates at L4 and provides a static IP per AZ. ALB is L7/HTTP-only and doesn't offer a static IP (DNS name only), so neither requirement fits it.

Check yourself — a Route 53 health check on your primary endpoint just started failing. Walk through what happens next.

The Failover routing policy stops returning the primary record and starts answering with the secondary record instead — no code deploy or manual cutover. How fast clients actually see the switch depends on the record's TTL, since resolvers keep serving a cached answer until it expires.

You can defend this when you can say why an Alias record can sit at the zone apex and a CNAME can't, trace what actually happens end to end when a Route 53 health check fails (not just "it fails over"), explain the CloudFront cache-hit-vs-miss path and why invalidation and URL-versioning solve the same problem differently, state when Global Accelerator earns its keep over CloudFront, and pick correctly between ALB, NLB, and GWLB for a workload described in one sentence.