Why a New DNS Record Still Returns NXDOMAIN
A record you just created can stay NXDOMAIN for minutes or a day. How DNS negative caching works, how to reproduce it, and a pre-cutover check that prevents it.
Ben Ennis
Published October 13, 2026
The failure looks like this. A deploy pipeline creates api-v2.example.com, then runs a smoke test against it. The test fails with NXDOMAIN. Someone runs dig @ns1.provider.net api-v2.example.com and gets the right address straight from the authoritative server. The record is correct. Clients still cannot resolve it, and they keep failing for 15 minutes, an hour, or until tomorrow, depending on a number in the zone’s SOA record that almost nobody reads.
Nothing is broken. A resolver asked for the name before the record existed, got a correct “no such name” answer, and is now doing its job by remembering it.
How negative caching works
Resolvers cache negative answers as well as positive ones. RFC 2308 defines two kinds:
- NXDOMAIN. No records of any type exist at the name.
- NODATA. The name exists, but not with the type you asked for. A name with only an A record returns NODATA for AAAA or TXT.
Neither answer carries the missing record, so it cannot carry that record’s TTL. Instead, the authoritative server includes the zone’s SOA record in the authority section, and the RFC sets the cache lifetime from it: “the minimum of the MINIMUM field of the SOA record and the TTL of the SOA itself.” The MINIMUM field is the seventh number in the SOA data defined by RFC 1035. In ns1.example.net. hostmaster.example.com. 1 7200 900 1209600 86400, it is 86400.
RFC 2308 also gives guidance on sensible values: “Values of one to three hours have been found to work well and would make sensible a default. Values exceeding one day have been found to be problematic.”
Reproduce it in five commands
You need dig and a zone you control. Pick a name that has never existed and has never been queried.
# 1. Read the zone's SOA: the TTL column and the last field matter
dig +noall +answer SOA example.com
# 2. Ask your usual resolver for the new name before it exists
dig +noall +comments +authority A canary-7f3a.example.com
# status: NXDOMAIN, and an SOA in AUTHORITY whose TTL is the negative TTL
# 3. Create the record at your DNS provider, then ask the authority directly
dig +short A canary-7f3a.example.com @"$(dig +short NS example.com | head -1)"
# returns the new address
# 4. Ask your resolver again
dig +noall +comments +authority A canary-7f3a.example.com
# still NXDOMAIN; the SOA TTL in AUTHORITY has counted down
# 5. Repeat step 4 after that TTL reaches zero
dig +short A canary-7f3a.example.com
# now resolves
Step 4 is the incident in miniature. The authority has the record, and the resolver serves its cached denial until the countdown ends. Every resolver that saw the early query keeps its own copy. That includes the public resolvers, your corporate resolver, CoreDNS in each cluster, and systemd-resolved on each host.
You can check any zone’s negative TTL without creating anything with the DNS lookup tool. Query a random name under the zone and read the TTL on the SOA in the authority section.
Four ways the window gets wider than you expect
Probe before create. The most common cause is the pipeline itself. A script that checks whether api-v2 already exists before creating it plants the negative cache entry it later trips over. So does a monitoring system that starts polling the new hostname before the DNS step runs, or a teammate who pastes the URL into a browser too early.
A missing parent hides its children. RFC 8020 says that after an NXDOMAIN, “all names and resource record sets (RRsets) at or below that node SHOULD be considered unreachable.” If a resolver cached NXDOMAIN for eu.example.com, a newly created api.eu.example.com can be denied without ever being queried. It bites when you create the first name under a new label.
DNSSEC can deny names nobody asked for. In a signed zone, a negative answer includes NSEC or NSEC3 records that prove a whole range of names does not exist. Validating resolvers may use that proof to answer for any name in the range. RFC 9077 fixed the lifetime of those records to “the lesser of the MINIMUM field of the SOA record and the TTL of the SOA itself,” the same rule as RFC 2308. A new name in a signed zone can therefore be denied for the negative TTL even if no one ever queried it.
NODATA when adding a type. Adding AAAA, TXT or CAA to a name that already has an A record follows the same rule. ACME DNS-01 validation is the usual victim. The _acme-challenge name gets queried, caches as NXDOMAIN or NODATA, and the TXT record published moments later stays invisible to that resolver.
A separate rule covers resolution failures such as timeouts and SERVFAIL. RFC 9520 requires resolvers to cache them for at least 1 second and says they “MUST NOT be cached for longer than 5 minutes.” A broken delegation therefore recovers within minutes of the fix. A cached NXDOMAIN does not.
What 43 developer zones use today
To see real values, we checked the negative TTL that 43 developer-infrastructure zones actually serve. It’s the same domain set as our CAA survey. On October 13, 2026 we queried a random, never-used label under each of 60 registrable domains through Cloudflare’s DNS-over-HTTPS JSON endpoint. We recorded the TTL on the SOA in the authority section. 43 returned NXDOMAIN. The other 17 answered NOERROR for the random name, usually because of a wildcard record, so a typo under those zones never produces NXDOMAIN at all. For every one of the 43, the served TTL equaled the lesser of the SOA TTL and MINIMUM, exactly as RFC 2308 specifies. The raw data is published as JSON.
| Negative TTL | Zones | Examples |
|---|---|---|
| 60 to 300 seconds | 15 | kubernetes.io, go.dev, rubygems.org, nuget.org, kernel.org, mozilla.org |
| 450 to 900 seconds | 13 | docker.com, python.org, grafana.com, hashicorp.com, debian.org |
| 30 minutes | 10 | gitlab.com, nodejs.org, letsencrypt.org, prometheus.io, digitalocean.com |
| 1 to 2 hours | 4 | helm.sh, redhat.com, ubuntu.com, hetzner.com |
| 24 hours | 1 | nginx.org |
The median was 900 seconds. The values follow DNS providers more than operators. All six Google Cloud DNS zones served 300 seconds, which matches the MINIMUM in the default SOA example in Google Cloud’s records documentation. All ten Cloudflare-hosted zones served 1,800 seconds.
Route 53 is the instructive case. The SOA example in the Route 53 documentation carries a MINIMUM of 86400, and the default SOA TTL is 900 seconds. The negative TTL is the lesser of the two, so it lands at 15 minutes. Of the 19 Route 53 zones in the full sample, 13 still carry the 86400 MINIMUM. The documentation suggests raising these TTLs to cut query charges, and it also names the cost: “if you ever erroneously delete a valid record and later recreate it, DNS resolvers will cache the negative response… for a longer period.” Raise only the SOA TTL on such a zone, and the latent one-day MINIMUM takes over.
During an incident
- Confirm it is negative caching. If the authoritative server answers correctly and the resolver returns NXDOMAIN with an SOA in the authority section, it is. Read that TTL. It tells you how long that resolver will hold the denial.
- Flush the caches you control. Restart or flush the cluster DNS cache, run
resolvectl flush-cacheson systemd hosts, and flush your corporate resolver. - Request flushes from public resolvers. Google Public DNS offers a flush cache page, and 1.1.1.1 offers a purge cache tool that takes a name and record type.
- Do not delete and recreate the record. That restarts the problem for anyone who queries while it is gone.
You cannot flush the other ISP and enterprise resolvers your users depend on. After you flush what you can, the remaining window is the negative TTL.
Prevent it: a pre-cutover check
Run this before any change that introduces a new name. It reads the SOA and prints the negative TTL a resolver would apply:
zone=example.com
read -r ttl min < <(dig +noall +answer SOA "$zone" | awk '{print $2, $NF}')
neg=$(( ttl < min ? ttl : min ))
echo "negative TTL for $zone: ${neg}s"
[ "$neg" -gt 900 ] && echo "warning: a premature lookup will be cached for over 15 minutes"
Then build the order of operations around it:
- Create first, reference later. Publish the record, confirm it at the authoritative servers, and only then let anything query it. Remove “does it exist?” probes from pipelines, or point them at the authority with
dig @ns. - Pre-create names you know you will need. A placeholder record for
api-v2published a day early cannot be cached as missing. - Lower the window ahead of migrations. Both Cloud DNS and Route 53 let you edit the SOA. Lowering the MINIMUM or the SOA TTL to 300 seconds a day before a migration limits the damage of a premature query. Restore it afterward if query cost matters.
- For ACME DNS-01, query the authority. Make your client wait for the TXT record at the authoritative servers before it asks the CA to validate.
Recommended reading
Frequently asked questions
Why does my new DNS record return NXDOMAIN when the authoritative server has it?+
How do I find a zone's negative caching TTL?+
What is the difference between NXDOMAIN and NODATA?+
Can I flush a cached NXDOMAIN?+
What negative TTL should a zone use?+
Does DNSSEC make negative caching worse?+
Tags: #dns, #negative-caching, #soa, #incident, #sre, #original-data