DNS returns an IP address. It doesn’t have to return the same IP address every time. The authoritative nameserver can return different IPs based on where the query originated, which backend is healthy, or how much traffic each backend should receive. DNS-based traffic routing uses this flexibility to implement geographic routing, load balancing, and failover without changing a line of application code.

GeoDNS#

The recursive resolver’s IP address reveals the approximate location of the client (or at least the ISP). The authoritative nameserver checks this IP against a geo-database and returns the IP of the nearest region’s load balancer.

A user in India querying api.example.com gets the Mumbai region’s IP. A user in Germany gets the Frankfurt region’s IP. This reduces latency by routing clients to the nearest data center, and it’s transparent to the client.

GeoDNS accuracy is limited by the recursive resolver: a user in Mumbai using Google’s 8.8.8.8 resolver sends a query from Google’s resolver IP, which may geolocate to a different city. EDNS Client Subnet (ECS) partially solves this: the recursive resolver includes a prefix of the client’s IP in the query, letting the authoritative server use the actual client location.

graph TD A[Client in Mumbai: resolve api.example.com] --> B[Recursive resolver sends query + client subnet] B --> C[Authoritative NS: check client geo] C --> D{Client region?} D --> |Asia-Pacific| E[Return IP: Mumbai load balancer] D --> |Europe| F[Return IP: Frankfurt load balancer] D --> |US| G[Return IP: Virginia load balancer] style A fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style B fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style C fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style D fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style E fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style F fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff style G fill:#000000,stroke:#00ff00,stroke-width:2px,color:#fff

Weighted Routing#

Return different IPs with different weights. Send 90% of traffic to the primary region, 10% to a canary region. Implemented by returning the primary IP 90% of the time and the canary IP 10% of the time in the authoritative server’s response.

This is coarser than application-level canary releases: DNS routing affects all traffic from a resolver simultaneously, not individual requests. Once a resolver caches the canary IP, all its clients go to canary until the TTL expires.

Health-Check Failover#

The authoritative nameserver monitors backend health via periodic HTTP or TCP checks. If the primary backend fails its health check, the nameserver stops returning its IP and returns only the backup IP.

With TTL 60 seconds, failover completes within 60 seconds of the health check detecting failure. The limitation: clients that have already cached the failed IP continue using it until their TTL expires. DNS failover is not instantaneous even with low TTL.

For faster failover, use anycast: multiple servers share the same IP address, BGP routes traffic to the nearest healthy one. When a server goes down, BGP converges in seconds. No DNS change needed.

At Salesforce#

Salesforce uses GeoDNS to route customers to the nearest data center. During a planned US East maintenance window, we pre-updated DNS weights to route US East customers to US West before the window opened. With TTL 120 seconds, the reroute completed within 2 minutes. Monitoring confirmed traffic shifted cleanly. After the window, we reversed the weights. The entire failover and failback happened without any application deployment.

What I’m Learning#

DNS-based routing is a blunt instrument: it operates at the resolver level, not the request level, and TTL creates a lag between configuration changes and traffic behavior. It’s best for coarse geographic routing and slow failover. Application-layer routing handles the fine-grained cases DNS can’t.

Have you used DNS-based routing for failover or geographic distribution, and what limitations did you hit?