Skip to content

DNS: Stub Resolver vs Recursive Resolver vs Authoritative Server

Mental model

Three roles. The stub asks. The recursive walks the tree. The authoritative owns the answer. Every DNS lookup touches all three.

What it looks like

"The DNS server is down" — without saying which of three completely different roles is broken.

What it really is

Stub resolver: runs on your machine. Knows nothing about DNS hierarchy. Reads /etc/resolv.conf (or systemd-resolved) to find a recursive resolver. Sends one question, gets one answer. That's it.

Recursive resolver: does the actual work. Receives a query from a stub, then iteratively queries the DNS hierarchy: root servers → TLD servers → authoritative servers. Caches results. Examples: 8.8.8.8, 1.1.1.1, your ISP's resolver, your corporate resolver.

Authoritative server: owns a DNS zone. Has the zone file with the actual records (A, AAAA, CNAME, MX, TXT, etc.). Returns definitive answers for its zone. Does not recurse — it either has the answer or it delegates to a child zone's NS records.

Why it seems confusing

"DNS server" is used for all three roles. A single machine can play multiple roles (e.g., a corporate DNS server that is both recursive and authoritative for internal zones). But the roles are logically distinct.

What actually matters

Resolution path:

stub → recursive → root (.) → TLD (.com) → authoritative (example.com)
     ← answer cached at recursive, returned to stub

  • The recursive resolver caches at every level. TTL (time-to-live) on each record controls how long the cache entry lives.
  • Negative caching: "this name does not exist" is also cached (with its own TTL from the SOA record).
  • The stub resolver may also cache (systemd-resolved does, glibc's stub does not).
  • /etc/nsswitch.conf controls whether the stub even uses DNS (vs /etc/hosts, mDNS, LDAP, etc.).
sequenceDiagram
    participant App as Application
    participant Stub as Stub Resolver
    participant Rec as Recursive Resolver
    participant Root as Root Server (.)
    participant TLD as TLD Server (.com)
    participant Auth as Authoritative (example.com)

    App->>Stub: resolve example.com
    Stub->>Rec: query example.com
    Rec->>Root: who handles .com?
    Root-->>Rec: .com NS servers
    Rec->>TLD: who handles example.com?
    TLD-->>Rec: example.com NS servers
    Rec->>Auth: A record for example.com?
    Auth-->>Rec: 93.184.216.34 (TTL 300)
    Rec-->>Stub: 93.184.216.34 (cached)
    Stub-->>App: 93.184.216.34

Common mistakes

  • Thinking the stub resolver walks the DNS tree (it doesn't — it asks the recursive and waits).
  • Confusing caching issues at the recursive with problems at the authoritative server.
  • Changing a DNS record and expecting instant propagation (TTL must expire at every caching layer).
  • Not realizing systemd-resolved is a local caching stub, not a recursive resolver.
  • Forgetting /etc/hosts is checked before DNS (per nsswitch.conf).

Small examples

Full resolution walk with dig:

dig +trace example.com
# .                  → root server (returns .com NS)
# .com               → TLD server (returns example.com NS)
# example.com        → authoritative (returns A record)

Checking which resolver the stub uses:

cat /etc/resolv.conf
# nameserver 127.0.0.53    ← systemd-resolved (local stub)
resolvectl status           # shows upstream recursive resolver

TTL and caching:

dig example.com
# ;; ANSWER SECTION:
# example.com.  300  IN  A  93.184.216.34
#                ^^^  TTL = 300 seconds of caching

One-line summary

Stub asks one resolver; recursive walks the tree; authoritative owns the answer.