The question this answers
How do clients find my infrastructure, and what does DNS decide that a load balancer cannot?
Users worldwide must reach api.example.com. European users should be served from the European region, American users from the American one, and if a region fails, everyone should be served from the survivor without anyone editing a config file.
A stable name in front of addresses that change, plus a decision point above the load balancer where health, geography and weight can steer traffic between entirely separate infrastructures.
The hop before the first hop
Every request begins with a name that is not an address. The client asks a resolver, the resolver walks the delegation chain to your authoritative zone, and the answer it gets back determines which infrastructure the request reaches. Nothing you own has been touched yet. The Computer Networking domain teaches how that resolution actually works; what matters here is that this hop is a *control point*, and it sits above everything else in your architecture.
That is why DNS is the only layer that can steer between two regions. A load balancer distributes across targets it can reach; it cannot send a user to a different continent. DNS can, because it answers the question earlier — before a connection exists. Regional failover, geographic routing and weighted rollouts between separate stacks are all DNS decisions for exactly this reason. See Multi-Region Deployment.
The record type usually matters less than the fact that a cloud entry point rarely has a fixed address. A load balancer's addresses change; the provider therefore offers an alias-style record that points at the resource itself rather than at an address, resolving to whatever the current addresses are. Pointing an A record at an address you copied out of the console is the classic way to build an outage that fires weeks later, when the provider replaces that address.
Records and routing policies
The records are the boring half and still cause outages: an A or AAAA pointing at a literal address, a CNAME that cannot exist at a zone apex, an alias record that can, MX and TXT for mail and verification, and NS delegating a subdomain to another zone. The apex restriction is the one that bites, because example.com cannot be a CNAME and the provider's alias record is the answer.
The routing policies are what make cloud DNS a routing layer rather than a lookup. Simple returns one answer. Weighted splits traffic by ratio, which is how a blue/green cutover between two stacks is performed. Latency or geolocation picks the nearest or the regionally correct endpoint. Failover returns the secondary only when a health check on the primary fails. Multi-value returns several healthy answers and lets the client pick.
Health-checked failover is the one that promises the most and delivers the least reliably, and the reason is in the next section: the answer you change is not the answer clients are using.
| Policy | What it answers with | Use it for | What it cannot do |
|---|---|---|---|
| Simple | One fixed answer set. | A single-region service with one entry point. | Anything conditional. |
| Weighted | One answer chosen by ratio. | Shifting traffic between two stacks during a migration or blue/green. | Give an exact split — caching skews the real ratio. |
| Latency / geolocation | The nearest or regionally mandated endpoint. | Multi-region serving and data-residency requirements. | Guarantee placement for a user behind a distant resolver. |
| Failover | Primary while healthy, secondary otherwise. | Regional disaster recovery with an active-passive stack. | Fail over faster than caches expire. |
| Multi-value | Several healthy answers at once. | Cheap client-side spreading without a load balancer. | Balance load — clients pick, and they pick badly. |
| Alias to a provider resource | The current addresses of a load balancer or CDN. | Anything at a zone apex, and any target whose addresses change. | Point at something outside the provider. |
The TTL is a promise about how slow your change will be
Every answer carries a time-to-live, and every resolver between you and the user is entitled to cache it for that long. Some cache longer. Some applications and runtimes cache resolved addresses for the lifetime of the process and never re-resolve at all, which means a change can be invisible to a long-running service until it restarts. The practical consequence is that a DNS change is not an atomic switch; it is a slow migration whose tail is measured in whatever the worst-behaved cache does.
This is what makes health-checked failover weaker than it sounds. The health check notices in seconds, the record changes in seconds, and users keep arriving at the failed region for as long as their resolvers and their client libraries hold the old answer. Designing for that means lowering the TTL *before* the event — 60 seconds costs more queries and buys faster convergence — and it means treating DNS failover as a coarse recovery tool rather than a high-availability mechanism. Real high availability inside a region belongs to the load balancer and its health checks, where failover is measured in seconds and no cache is involved. See High Availability.
The same asymmetry explains the classic incident: a team decommissions the old load balancer immediately after the record is updated, and traffic from cached answers hits a dead address for the next twenty minutes. The old target must outlive the record change by several TTLs, and the safe sequence is to lower the TTL first, wait out the old TTL, then change, then wait again before decommissioning anything.
$ dig +noall +answer api.example.com
api.example.com. 3600 IN A 198.51.100.10 <- TTL 3600: an hour of tail
THE INCIDENT — record changed, old target removed at once
T+0 record now points at 198.51.100.20
T+0 old load balancer deleted <- the mistake
T+0.. ~40% of traffic still resolving to .10 from caches
users see connection timeouts; the new stack shows healthy and idle
every dashboard on the new infrastructure is green
T+60m caches finally expire; traffic completes its migration
THE SAFE SEQUENCE
step 1 lower TTL to 60 on the existing record (do this a day ahead)
step 2 wait out the OLD TTL — 3600s — so every cache holds the 60s value
step 3 change the record to the new target
step 4 keep the old target serving for several minutes; watch its request count
fall to zero rather than assuming it has
step 5 decommission, then restore a longer TTL
NOTE some client runtimes cache a resolved address for the life of the process
and never re-resolve. For those, no TTL is short enough.Key points
- DNS is the hop before the first hop, and the only layer that can steer a user between separate regional infrastructures.
- Point records at provider resources with alias-style records, not at addresses copied from a console — those addresses change.
- Routing policies (weighted, latency, geolocation, failover, multi-value) make cloud DNS a routing layer, not a lookup table.
- The TTL is a promise about how slow a change will be, and some clients cache a resolved address for the life of the process.
- DNS failover is coarse disaster recovery; real in-region high availability belongs to the load balancer.
The loop, answered
Every field is required, which is why no lesson here can recommend something without saying what it costs and what simpler thing to consider first.
- • A client asks a resolver, which walks the delegation chain and caches the answer for its TTL.
- • Your authoritative zone applies a routing policy — weight, latency, geography, health — to decide which answer to return.
- • Health checks probe endpoints from multiple locations and remove unhealthy answers from the candidate set.
- • An alias-style record resolves at query time to the current addresses of a provider resource, so the record never goes stale.
- • The client connects to the address it received, and nothing about that connection can be influenced by DNS afterwards.
- • Own the TTL strategy per record: low before a planned change, higher afterwards to control query cost.
- • Own the zone as code with the rest of the infrastructure — a hand-edited zone is the most consequential untracked change in the stack.
- • Own registrar and delegation hygiene: expiry, lock status and correct NS records are single points of total failure.
- • Own the health-check configuration, including what the checked endpoint actually verifies — a static file proves nothing about the application.
- • Own the decommission sequence, and confirm by request count that the old target is idle before deleting it.
- • A stale cached answer sending a fraction of users to a decommissioned address, presenting as an outage that only affects some people.
- • A client library caching a resolved address for the process lifetime, so a change never reaches long-running services until they restart.
- • A record pointing at a literal address that the provider later reassigns — an outage seeded weeks earlier.
- • A health check probing a path that is always healthy, so failover never triggers on a real failure.
- • A registrar or delegation problem — an expired domain, a wrong NS record — which takes everything down at once and is not fixed by any infrastructure change.
- • Query volume scales with users and inversely with TTL, and it is billed per query on managed services.
- • Very low TTLs raise both query cost and resolver load, so convergence speed is bought rather than free.
- • A zone with many records is cheap; the constraint is change management, not the resolver.
- • Geographic and latency policies scale naturally with regions, which is why DNS is the multi-region entry point.
- • DNS is a public, unauthenticated lookup by default: your zone reveals your infrastructure names to anyone who asks.
- • Registrar and zone access is the highest-value credential in the whole stack; control of the zone is control of the traffic.
- • Dangling records — a name still pointing at a released resource — are the mechanism of subdomain takeover, and they accumulate silently. See Public Exposure, Read With Context.
- • DNSSEC and a private internal zone for internal names are the two controls most environments should have and most do not.
- • Managed zones cost a small amount per hosted zone plus a per-query charge, so cost scales with traffic and with low TTLs.
- • Health checks are billed per check per endpoint, which is modest but multiplies across regions and paths.
- • The genuine cost is not money: it is the change latency the TTL imposes on every cutover and every failover.
- • A dangling record costs nothing until it costs a security incident.
- • Query volume by record and by response code, which reveals both traffic shifts and misconfigured clients.
- • Health-check status history, which is the record of what your failover policy actually saw.
- • Request counts on the *old* target during a cutover — the only honest measure of how much traffic has actually migrated.
- • The signal that lies: "the record is updated". It says nothing about what resolvers are still answering, which is the number that matters.
- • A load balancer's own health checks and target registration for everything inside one region — faster, cache-free, and the correct tool.
- • A CDN or anycast entry point, when the goal is proximity rather than choosing between distinct regional stacks. See CDN as Infrastructure.
- • Service discovery inside the cluster for service-to-service resolution, rather than public DNS names for internal traffic.
- • The provider's default generated hostname, for an internal or pre-production service where a custom name buys nothing.
- • Buys a stable name and a routing decision above the infrastructure; costs a cache you do not control on every change.
- • A low TTL buys faster convergence; costs query volume, query charges and resolver load.
- • Health-based failover buys automatic regional recovery; costs a convergence time that is a distribution, not a number.
What people believe, and what is true
DNS failover gives high availability.
It gives coarse recovery bounded by cache expiry and client behaviour. In-region availability comes from a load balancer with health checks, where failover takes seconds and no cache is involved.
The change is live once the record is updated.
It is live for resolvers that ask after the old TTL expires. Traffic migrates over a distribution, and some clients never re-resolve until they restart.
A low TTL is always better.
It buys convergence speed and costs query volume and charges. The right pattern is to lower it before a planned change and raise it afterwards.