Summary
- RFC 9520 requires resolvers to cache resolution failures for at least one second and no more than five minutes. A matching entry suppresses outgoing work; it does not certify NXDOMAIN, NODATA or any other fact about the name.
- Failure exists only after no available server and transport returns useful data. One useful answer, referral or authoritative negative response defeats the failure verdict.
- The defensible ledger records the attempted path set, retry count, joined client cohort, failure-cache key and scope, backoff, ancestor queries suppressed, resource pressure and the first controlled recovery probe.
When a silent zone made a healthy parent absorb the noise
On 4 October 2021, a maintenance command unintentionally disconnected Facebook's data centres from the company's backbone. Meta's incident account explains that its authoritative DNS sites withdrew their BGP advertisements when they could no longer reach those data centres. The DNS servers were still operating. To the rest of the Internet, however, their addresses had become unreachable.
The silence did not stay at Facebook's boundary. Verisign measured roughly 7,000 ordinary .com and .net queries per second for facebook.com, instagram.com and whatsapp.net. During the nearly six-hour outage, the rate climbed above 900,000 per second. Queries from the most active Google and Cloudflare resolver sources rose to peaks around 7,000 and 2,000 times their respective ordinary rates for those names.
The parent zones had not lost the delegations. Re-asking them could not restore an authoritative route. Yet repeated resolution attempts transferred the cost of one unreachable zone into healthy infrastructure above it. The incident gave physical scale to a design question that can look trivial in a resolver configuration: when is a machine entitled to stop asking?
RFC 9520 answers without turning silence into truth. A resolver that has received no useful response from any available server must cache that resolution failure. When the same failure matches a later request, it must not send corresponding outgoing queries until the entry expires. The cache is a temporary right to refuse more work, not a record that the queried name is absent.
That difference is the article's controlled object. NXDOMAIN and NODATA carry useful negative information. A resolution failure carries no useful information about whether the data exists. One may support a DNS-content conclusion for a bounded TTL. The other supports only a local backpressure decision.
The verdict begins only after the paths end
Resolvers normally have choices. A stub may know several recursive addresses. An iterative resolver may know several authoritative names, several addresses for each name and more than one DNS transport. A timeout on one address is therefore not yet a resolution failure. Neither is one SERVFAIL, one REFUSED response or one broken transport.
RFC 9520 defines a useful response as requested data, a referral to a descendant zone, or an indication that no data exists at the queried name. If any available server returns one, resolution did not fail. This makes path custody the first evidence requirement. Before a resolver inserts a failure entry, it should be able to show the eligible server-address and transport set, every attempt and the terminal result of each.
Retry remains permitted but bounded. For one query sent to one server address over one transport, a resolver must not retry more than twice after the first transmission: three queries in total. It may try another known transport to the same server when that transport is available and consistent with the resolver's security policy. RFC 9520 deliberately does not impose one timeout. It notes that ordinary implementations may use values from roughly three to thirty seconds.
The absence of a universal timeout is not a defect. Path latency, transport establishment, anycast behaviour and service budgets differ. The obligation is to expose the chosen value and the evidence behind it. A five-second timeout on one fleet and a twenty-second timeout on another are not contradictory. A dashboard that says only server failed while hiding the attempt set and timing is incomplete.
Failure has several causes and only one narrow effect
SERVFAIL is a broad signal. An authoritative server may have no valid zone data. A recursive server may have exhausted its own work, failed validation or met another condition. REFUSED often represents policy: an authoritative server may not serve the queried zone, or a recursive service may reject a source outside its access list. A timeout says no response arrived in time. ICMP unreachable, TCP refusal or a TLS handshake failure can end a transport attempt earlier.
Delegation loops and alias loops fail differently. In a delegation loop, two or more zones can depend on names inside one another until an incautious resolver emits attack-scale work. A CNAME or DNAME loop can send name processing around a cycle. DNSSEC validation can fail because of signatures, keys, denial-of-existence records, time or another chain defect. FORMERR can expose message or EDNS compatibility trouble.
The cache may preserve these distinctions, but its common effect is small: stop corresponding outgoing queries for a bounded interval. It must not rewrite REFUSED as SERVFAIL, turn validation failure into unsigned data, or tell a client that the name does not exist. Cause-specific evidence is valuable because recovery and accountability differ. It is not authority to invent a stronger answer.
Extended DNS Errors make this boundary easier to operate. An EDE can say Cached Error, No Reachable Authority, DNSSEC Bogus or another more descriptive reason. RFC 8914 is explicit that EDE does not change RCODE processing. The text can aid logs and clients; it cannot convert a cached failure into authenticated zone content.
One upstream transaction, not one per impatient client
Consider a popular name whose authoritative servers have all stopped responding. While the resolver waits for timeout, hundreds of clients may ask the same QNAME, QTYPE and QCLASS. A resolver that joins those requests attaches them to one outstanding resolution transaction. A resolver that does not can send one upstream query for each client request, then retry each one.
The first design keeps demand at the boundary. The second reproduces demand inside the DNS hierarchy and multiplies it by the number of addresses, transports and retries. The 2021 DNS-OARC botnet experiment cited by RFC 9520 gives the mechanism another measured form. A sinkholed domain averaged about 50 queries per second when its authoritative service answered normally. When every authoritative returned SERVFAIL, the rate reached about 60,000 per second, and unchanged root and TLD layers also received more traffic.
Joining protects more than capacity. RFC 5452 explains how multiple equivalent outstanding queries enlarge the birthday-attack surface: a forged response can match any one of several open transactions. Failure containment therefore has three distinct controls. Join identical demand. Limit retries on each address and transport. Cache the exhausted result. None substitutes for the other.
The cache starts after exhaustion, not when the first impatient client arrives. Joining decides how many transactions are simultaneously alive. The retry ceiling decides how much work each path may receive. The failure entry decides how long matching future demand remains local. A credible implementation reports all three.
A floor, a ceiling and a recovery debt
RFC 9520 requires at least one second of failure caching and prohibits more than five minutes. The minimum should be configurable. Repeated failures may use linear or exponential backoff, still below the five-minute ceiling.
Those numbers describe a safety envelope, not a universal optimum. A longer interval sharply reduces repeated upstream work but extends the time between service recovery and the resolver's next attempt. A shorter interval improves responsiveness to transient repair but permits more load during a persistent outage. Backoff can protect an authority that remains sick; it can also make the last failed observation dominate clients after the authority is healthy.
That trade creates recovery debt. Every inserted failure should carry a key, scope, cause set, insertion time, selected duration, backoff stage, expiry and configuration version. When it expires, the resolver should release one controlled recovery probe rather than an accumulated herd. The first useful response ends the local basis for suppression. The evidence should record how long clients continued to receive cached failure after recovery became possible.
Implementation-specific keying matters. A DNSSEC validation failure may be cached for one name, class and type. An unreachable address may justify an address-scoped state. A SERVFAIL from one server may not justify suppressing every query to every server. RFC 2308 used specific query-and-server scopes when failure caching was optional. RFC 9520 makes failure caching mandatory while leaving room for designs that distinguish conditions. That freedom transfers responsibility to implementers to document what one failure entry covers.
The parent is not a reset button
When every authoritative server for a zone is non-responsive, some resolvers have historically asked the parent for delegation information again. RFC 4697 prohibited aggressive NS requerying to the parent in that condition. RFC 9520 broadens the obligation: limit queries to the parent and every other ancestor just as matching queries to the failed zone are limited.
This is a powerful separation of authority. A healthy parent can repeat the same delegation accurately and still be unable to repair the child. Its answer is not a command to keep retrying. Suppressing the ancestor query does not declare the delegation wrong, stale or changed. It records that, for this bounded failure interval, another identical look upward would not supply useful new work.
An operator should therefore count ancestor queries that the cache prevented. The metric reveals load displaced by failure and proves whether containment reached the hierarchy above the failed zone. It also helps isolate a real delegation change: after expiry, a controlled query may discover new addresses or a repaired cut. Permanent suppression would conceal that change; bounded suppression protects the parent while preserving future discovery.
DNSSEC failure needs a cache because its TTL cannot be trusted
RFC 4035 originally allowed security-aware resolvers to maintain a BAD cache for repeated validation failures. Its reasoning was practical: persistent signing mistakes can make repeated queries expensive, yet data that failed validation cannot supply a trustworthy TTL. Implementations therefore assign a small local duration and protect the BAD cache from becoming a denial-of-service amplifier.
RFC 9520 changes the permission to a requirement. DNSSEC validation failures must be cached within the same bounded failure logic. That does not permit the resolver to return the invalid RRset as validated data. It permits the resolver to remember that repeated resolution work did not produce acceptable data.
This is where an EDE can add useful explanation without changing authority. A client may learn that the resolver is serving a cached error or observed bogus validation. The operator still needs the chain evidence, validation time, local cache scope and next probe. A text label alone does not prove which signature, key or denial record failed.
Serve Stale answers a different question
RFC 8767 permits a resolver to return expired data under a defined stale-answer policy when refresh fails. It recommends limiting refresh attempts to a failing authority, commonly with a thirty-second failure-recheck interval. The mechanism improves continuity when old usable data remains in cache.
RFC 9520 is broader and conceptually different. A resolver may have no stale data. It may be resolving a new name or type. Its stale policy may be disabled. It must still avoid issuing unbounded failing work. A stale answer says, “this was previously useful data and policy permits temporary reuse.” A cached resolution failure says, “no available path produced useful data, so I will not repeat the same work until this local interval ends.”
The evidence row should name both states. Otherwise a client receiving an answer and a client receiving an error may look like the same successful containment event. Continuity and load containment can cooperate, but they do not share a truth claim.
The containment cache can itself be attacked
An attacker can generate high-cardinality names or types that all fail, trying to consume failure-cache memory and processing. RFC 9520 therefore requires practical resource bounds. Operators need entry counts, bytes, insertion and eviction rates, per-client or per-zone concentration, CPU spent classifying failures and the number of entries discarded before expiry.
There is a second risk. Failure messages are not signed DNS data. An off-path attacker who can forge matching failure responses may cause the resolver to stop querying a real authority for the backoff interval. The five-minute ceiling makes the effect temporary, but repeated spoofing can renew it. The correct response is not to pretend the cache contains authoritative truth. It is to keep the interval bounded, retain response and transport evidence, reduce multiple outstanding transactions, and watch for failure patterns that disagree across servers or vantages.
The cache is therefore a circuit breaker with an evidence burden. Without a bound, retries can become a distributed attack on authorities and parents. Without a scope and expiry, suppression can become a denial service of its own.
The minimum ledger for a defensible failure
For each decision, preserve QNAME, QTYPE, QCLASS, first-seen time and a joined-client cohort identifier. Name the zone cut, NS set, server addresses, resolver vantage and every transport. For every attempt, record start, finish, retry ordinal and raw terminal result. Record whether any response met the useful-response test.
If all paths fail, store the failure classes, RCODEs, transport errors, DNSSEC result and any EDE separately. Then store the cache key, scope, insertion, configured interval, backoff stage, expiry and eviction priority. Record parent and ancestor queries suppressed, stale-data availability and whether a separate Serve Stale policy answered the client.
At fleet level, compare incoming client queries with joined groups and outgoing authoritative or ancestor queries. Publish the amplification ratio, latency, CPU, memory and cache cardinality. On expiry, identify the recovery probe, its target and the first useful response. Measure client-visible recovery lag rather than assuming expiry equals restoration.
This ledger keeps the decision local and reversible. It does not ask a registry, standards body or parent zone to certify one resolver's timer. It asks the resolver operator to prove why work stopped and when it began again.
Sources
- RFC 9520 — Negative Caching of DNS Resolution Failures
- RFC 2308 — Negative Caching of DNS Queries
- RFC 4035 — DNSSEC Protocol Modifications
- RFC 4697 — Observed DNS Resolution Misbehavior
- RFC 5452 — DNS resilience against forged answers
- RFC 8767 — Serving Stale Data
- RFC 8914 — Extended DNS Errors
- Meta Engineering — More details about the October 4 outage
- Verisign — Observations on Resolver Behavior During DNS Outages
- DNS-OARC 35 — Botnet Traffic Observed at Various Levels of the DNS Hierarchy
- Heng Lu — Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption
- Heng Lu — Running Code Is Primary
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance
