DNS Engineering

Master DNS as a critical infrastructure component. Covers DNS architecture, caching, security extensions (DNSSEC), split-horizon DNS, DNS-based service discovery, failover patterns, and the DNS problems that cause the most outages.

DNS Engineering is the practice of designing, operating, and troubleshooting the Domain Name System as a production-grade, distributed service. It matters when a service must resolve millions of queries per second, tolerate regional outages, provide low latency across continents, and ensure high availability under load. DNS Engineering is not just configuring zones or setting TTLs; it is the discipline of making DNS a performant, observable, and resilient component of the network stack—where every query has a lifecycle, every record is a signal, and every failure reveals deeper system behavior.

Resolving Queries with Predictable Latency

The primary task of DNS Engineering is to ensure that queries resolve quickly and consistently. A name resolution begins with a client sending a DNS query over UDP (or TCP) to a resolver, which may traverse multiple recursive servers before returning an answer. The root servers, TLD servers, and authoritative servers form a hierarchical chain that must be optimized.

A typical query starts with a client sending a DNS query packet to a recursive resolver:

; Question
example.com. IN A

; Answer
example.com. 300 IN A 192.0.2.1

The resolver may cache responses, and the TTL on each record controls how long it remains valid. A common mistake is setting a global TTL of 300 seconds, but neglecting to adjust it per record type or per service. A 300s TTL means that a change to an A record is not fully propagated for five minutes—too long for canary rollouts or blue-green deployments.

To tune latency, engineers configure resolvers to use multiple upstream servers. In unbound, a popular recursive DNS server, the configuration includes:

server:
    # Use multiple upstream servers with round-robin
    upstream:
        - 1.1.1.1
        - 1.0.0.1
        - 8.8.8.8
        - 8.8.4.4

    # Enable DNSSEC validation
    dnssec: yes

    # Reduce latency by prefetching
    prefetch: yes
    prefetch-roots: yes

    # Optimize for low latency
    cache-max-ttl: 3600
    cache-min-ttl: 300
    aggressive-nsec: yes

The resolver uses edns0 to enable larger UDP packets (up to 4096 bytes), reducing the need for TCP fallback. A query with DO (DNSSEC OK) bit set triggers DNSSEC validation, which can add 20–100ms of latency per query.

When a resolver cannot answer a query from cache, it performs iterative resolution. It queries the root servers, then the TLD (e.g., .com), then the authoritative servers for the domain. The dig command reveals this chain:

$ dig @a.root-servers.net example.com A +trace

; <<>> DiG 9.16.1 <<>> @a.root-servers.net example.com A +trace
; (1 server found)
;; global options: +cmd
.                       518400  IN  NS  a.root-servers.net.
a.root-servers.net.     518400  IN  A   198.41.0.4
[...]
com.                    172800  IN  NS  a.gtld-servers.net.
a.gtld-servers.net.     172800  IN  A   192.5.6.30
[...]
example.com.            300     IN  NS  ns1.example.com.
ns1.example.com.        300     IN  A   192.0.2.1
example.com.            300     IN  A   192.0.2.1

The +trace flag shows the full chain of queries. Engineers must monitor the trace time and validate that recursive servers are properly configured to use authoritative servers’ NS records.

Managing DNS Zones with High Availability

Authoritative DNS servers must serve zone files with low latency and high availability. Zone files are typically stored as text files with SOA, NS, A, CNAME, and MX records.

A typical zone file for example.com:

$ORIGIN example.com.
$TTL 300
@       IN  SOA ns1.example.com. hostmaster.example.com. (
                2024050101 ; serial
                3600       ; refresh
                900        ; retry
                604800     ; expire
                300        ; minimum
                )
        IN  NS  ns1.example.com.
        IN  NS  ns2.example.com.
        IN  A   192.0.2.1
www     IN  CNAME www.example.com.
mail    IN  A   192.0.2.10
mail    IN  MX  10 mail.example.com.

The SOA record defines the zone’s origin and refresh behavior. The serial number is critical: when it increases, secondary servers fetch the zone via AXFR or IXFR. The refresh interval determines how often a slave server checks for updates.

For high availability, zones are served by multiple authoritative servers. A common pattern uses glue records to prevent circular dependencies:

example.com.            IN  NS  ns1.example.com.
ns1.example.com.        IN  A   192.0.2.10
ns2.example.com.        IN  A   192.0.2.11

Without glue records, a resolver must first resolve ns1.example.com. before it can query ns1.example.com for the example.com zone. This adds a round-trip and increases latency.

When a zone changes, the master server updates the serial and notifies secondaries. The notify mechanism uses UDP packets to inform slaves of changes. A slave server queries the master with AXFR (full zone transfer) or IXFR (incremental zone transfer) to fetch updates.

The axfr command from bind tools:

$ dig @ns1.example.com example.com AXFR

; <<>> DiG 9.16.1 <<>> @ns1.example.com example.com AXFR
; (1 server found)
;; global options: +cmd
example.com.            300     IN  SOA ns1.example.com. hostmaster.example.com. 2024050101 3600 900 604800 300
example.com.            300     IN  NS  ns1.example.com.
example.com.            300     IN  NS  ns2.example.com.
example.com.            300     IN  A   192.0.2.1
www.example.com.        300     IN  CNAME www.example.com.
mail.example.com.       300     IN  A   192.0.2.10
mail.example.com.       300     IN  MX  10 mail.example.com.

The IXFR transfer is more efficient when only a few records have changed. The master sends a IXFR packet that includes the new serial and a list of changed records, allowing the slave to apply only the deltas.

Ensuring Resilience with Failover and Load Balancing

DNS Engineering ensures that services remain available during failures. The most common pattern is using multiple A records for a single name to provide load balancing and failover.

api.example.com.        30 IN  A   192.0.2.10
api.example.com.        30 IN  A   192.0.2.11
api.example.com.        30 IN  A   192.0.2.12

When a client queries api.example.com, the resolver returns all three IP addresses. The order of the responses determines the initial load balancing strategy. The round-robin pattern is the default, but clients may use the weight and priority fields to influence routing.

api.example.com.        30 IN  A   192.0.2.10
api.example.com.        30 IN  A   192.0.2.11
api.example.com.        30 IN  A   192.0.2.12
api.example.com.        30 IN  A   192.0.2.13

To implement weighted load balancing, engineers use RRsets with A records of different weights:

api.example.com.        30 IN  A   192.0.2.10  ; weight 100
api.example.com.        30 IN  A   192.0.2.11  ; weight 50
api.example.com.        30 IN  A   192.0.2.12  ; weight 50

Clients receive a list of IPs, and the probability of choosing each IP is proportional to its weight. This is especially useful when services have different capacities—e.g., a high-memory instance handles more traffic than a low-memory one.

For failover, DNS engineers use short TTLs and a health-check system that updates DNS records dynamically. When a server becomes unreachable, a health check process updates the A record for that server with a new IP or removes it.

The nsupdate command updates a zone dynamically:

$ nsupdate -k /etc/dns/keys/example.com.key
> server ns1.example.com
> update add api.example.com. 30 IN A 192.0.2.10
> send
> quit

This command uses TSIG (Transaction Signature) for authentication. The key file, generated by dnssec-keygen, contains the shared secret and algorithm.

When a service goes down, a script may update the zone to remove the failing IP:

$ nsupdate -k /etc/dns/keys/example.com.key
> server ns1.example.com
> update delete api.example.com. A 192.0.2.10
> send
> quit

The client now sees only the remaining IPs, providing automatic failover.

Observing and Debugging DNS with Real Tools

DNS Engineering relies on observability. Engineers use dig, nslookup, tcpdump, and dnstap to diagnose issues.

A common failure mode is a resolver returning stale data due to a misconfigured TTL. The dig command with +stats reveals query details:

$ dig +stats example.com A

;; Query time: 18 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Thu May 02 12:00:00 UTC 2024
;; MSG SIZE  rcvd: 120

;; OPT PSEUDOSECTION:
; EDNS: version 0; flags: do; udp: 4096
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            300     IN      A       192.0.2.1

;; Query time: 18 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Thu May 02 12:00:00 UTC 2024
;; MSG SIZE  rcvd: 120

The query time and rcvd size indicate performance and response size.

For deeper analysis, engineers use tcpdump to capture DNS traffic:

$ sudo tcpdump -i any -n -s 0 -vvv port 53

This captures all DNS traffic on port 53, showing packet headers, flags, and payloads. The tcpdump output reveals when a resolver falls back from UDP to TCP:

IP (tos 0x0, ttl 64, id 12345, offset 0, flags [none], proto UDP (17), length 128)
    192.168.1.1.55432 > 1.1.1.1.53: [udp sum ok] 12345+ A? example.com. (58)
    [length 128]
    1.1.1.1.53 > 192.168.1.1.55432: [udp sum ok] 12345 128 bytes (88)
    [length 128]
    192.168.1.1.55432 > 1.1.1.1.53: [tcp sum ok] 12345:12345(12345) 128 bytes (88)
    [length 128]

The tcpdump output shows the initial UDP query, the UDP response, and the TCP-based follow-up. This pattern is common when a response exceeds 512 bytes.

For centralized observability, engineers use dnstap, a binary logging format for DNS. unbound can generate dnstap logs:

dnstap:
    enable: yes
    filename: /var/log/dnstap/dnstap.log
    type: binary
    socket: unix
    socket-path: /run/dnstap.sock
    client: yes
    server: yes
    query: yes
    response: yes
    cache: yes
    validation: yes

The dnstap binary logs are consumed by tools like dnstap-reader, Prometheus, or Grafana, providing a unified view of DNS traffic across the network.

Handling DNSSEC and Validation

DNS Engineering includes DNSSEC (DNS Security Extensions) to ensure data integrity and authenticity. A DNSSEC chain starts with a DS record in the parent zone, pointing to a DNSKEY record in the child zone.

To validate a query, a resolver performs a chain of validations:

  1. Fetch the DNSKEY from the zone.
  2. Verify the RRSIG on the DNSKEY record.
  3. Use the DNSKEY to verify the RRSIG on the A record.
  4. Verify the DS record in the parent zone using a DNSKEY from the parent.

A failure in any step breaks the chain. Common issues include mismatched algorithm values, expired RRSIG signatures, and missing DS records.

The dig command with +dnssec shows the validation process:

$ dig +dnssec example.com A

;; OPT PSEUDOSECTION:
; EDNS: version 0; flags: do; udp: 4096
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            300     IN      A       192.0.2.1
example.com.            300     IN      RRSIG   A 5 2 300 2024050101 2024050201 12345 example.com. (...)
example.com.            300     IN      DNSKEY  5 2 300 2024050101 2024050201 12345 example.com. (...)

;; AUTHORITY SECTION:
example.com.            300     IN      DS      12345 5 2 123456789abcdef123456789abcdef123456789abcdef

The RRSIG record contains the signature, and the DNSKEY contains the public key. The DS record in the .com zone references the DNSKEY in example.com.

A silent failure occurs when the algorithm field in the DNSKEY does not match the algorithm used to sign the RRSIG. This causes validation to fail, but the resolver returns the data anyway—leading to a false sense of correctness. Engineers must monitor validation success rates and alert on failed chains.

Deployment and Maintenance

DNS Engineering includes systematic deployment of changes. Engineers use version-controlled zone files, with git for tracking changes.

$ git log --oneline --graph
* 3a1b2c3 Add new API server IP (2024-05-02)
* 4d5e6f7 Update TTL for www (2024-05-01)
* 7g8h9i0 Initial zone setup (2024-04-30)

A change is committed, tested in a staging environment, then deployed using nsupdate or AXFR to the production master.

A common deployment pattern uses a script that:

  1. Updates zone files.
  2. Increments the SOA serial.
  3. Sends NOTIFY messages to all secondary servers.
  4. Verifies the zone with dig and axfr.

This ensures that changes are applied consistently and validated before going live.

This page was rewritten on 18 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.