DNSSEC lets a validating resolver prove that an answer for your domain came from your zone unaltered. For a site owner, almost all of the risk sits in one record you rarely look at: the DS record your registrar publishes in the parent zone. When it matches your DNS provider’s key, nothing visible changes; when it doesn’t, every validating resolver returns SERVFAIL for your whole domain.

What a validated answer looks like

Live capture, 26 September 2026. Asking Cloudflare’s resolver for cloudflare.com, a signed zone, with the DNSSEC OK bit set (+dnssec):

dig @1.1.1.1 cloudflare.com A +dnssec
; <<>> DiG 9.10.6 <<>> @1.1.1.1 cloudflare.com A +dnssec
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19119
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
...
;; ANSWER SECTION:
cloudflare.com.		9	IN	A	104.16.132.229
cloudflare.com.		9	IN	A	104.16.133.229
cloudflare.com.		9	IN	RRSIG	A 13 2 300 20260927154148 20260925134148 34505 cloudflare.com. ndOknAF/TosEG/vNlsODSEwL7wlAjcYDApBRZqZF2tO3Py9uS+Ac1CuN biKZaDb82bwZNRyQS8p8wHzK5lkrbA==
...
;; WHEN: Sat Sep 26 23:46:39 KST 2026
;; MSG SIZE  rcvd: 185

Three things matter here:

  • ad in the flags line. RFC 4035 lets a resolver set the Authenticated Data bit only when it considers every record in the answer and authority sections authentic. It is the resolver’s verdict, so it only means something if you trust the resolver and the path to it.
  • do in the EDNS line shows that dig asked for DNSSEC records, which is why the RRSIG appears. DiG sets the AD bit in its queries by default, so a validating resolver reports ad even without +dnssec; the option is what makes the signatures visible.
  • The RRSIG covers the A records, uses algorithm 13 (ECDSA P-256 with SHA-256) and key tag 34505, and is valid from 25 September 13:41:48 to 27 September 15:41:48 UTC. A validator rejects a signature outside that window, which is why expired signatures are a classic cause of SERVFAIL.

The DS record is the part your registrar holds

Live capture, 26 September 2026. The DS record for cloudflare.com (served by the .com zone) and the keys the cloudflare.com zone itself publishes:

dig @1.1.1.1 cloudflare.com DS +dnssec
dig @1.1.1.1 cloudflare.com DNSKEY +multiline +noall +answer
; <<>> DiG 9.10.6 <<>> @1.1.1.1 cloudflare.com DS +dnssec
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
cloudflare.com.		86400	IN	DS	2371 13 2 32996839A6D808AFE3EB4A795A0E6A7A39A76FC52FF228B22B76F6D6 3826F2B9
cloudflare.com.		86400	IN	RRSIG	DS 13 2 86400 20260930005917 20260922234917 41446 com. dXfZkTrBwwnAiSH1U2LGoSH8Ko9LwwgXyBfPS/NmohpBT0Ksuh/ZkD7w 89naIuC0FTKU4KN863wvRYDZKS5pjA==
...
cloudflare.com.		1561 IN	DNSKEY 256 3 13 (
				oJMRESz5E4gYzS/q6XDrvU1qMPYIjCWzJaOau8XNEZeq
				CYKD5ar0IRd8KqXXFJkqmVfRvMGPmM1x8fGAa2XhSA==
				) ; ZSK; alg = ECDSAP256SHA256 ; key id = 34505
cloudflare.com.		1561 IN	DNSKEY 257 3 13 (
				mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+Gq
				JxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==
				) ; KSK; alg = ECDSAP256SHA256 ; key id = 2371

The DS fields are key tag 2371, algorithm 13, digest type 2 (SHA-256), and the digest. Put together with the signatures, the chain for this answer reads:

Link Record Published by What it vouches for
1 DS 2371 13 2 3299… The .com registry, signed by a .com key (tag 41446) The cloudflare.com key with tag 2371
2 DNSKEY 257 (KSK, tag 2371) cloudflare.com The zone’s DNSKEY set; a separate query showed its RRSIG uses key tag 2371
3 DNSKEY 256 (ZSK, tag 34505) cloudflare.com Ordinary records such as the A records above

Only link 1 lives outside your DNS provider. Your provider serves and rotates the keys; your registrar passes the DS to the registry, which publishes it in the parent zone. Everything below is about keeping those two in agreement.

Live capture, 26 September 2026. DS records fetched directly from the .com, .org and .io name servers (dig’s comment lines filtered out):

dig @a.gtld-servers.net cloudflare.com DS +norec +noall +answer | grep -vE '^;|^$'
dig @a.gtld-servers.net cloudflare.net DS +norec +noall +answer | grep -vE '^;|^$'
dig @a0.org.afilias-nst.info isc.org DS +norec +noall +answer | grep -vE '^;|^$'
dig @a0.org.afilias-nst.info vuejs.org DS +norec +noall +answer | grep -vE '^;|^$'
dig @a0.nic.io desec.io DS +norec +noall +answer | grep -vE '^;|^$'
cloudflare.com.		86400	IN	DS	2371 13 2 32996839A6D808AFE3EB4A795A0E6A7A39A76FC52FF228B22B76F6D6 3826F2B9
cloudflare.net.		86400	IN	DS	2371 13 2 90F710A107DA51ED78125D30A68704CF3C0308AFD01BFCD7057D4BD0 3B62C68B
isc.org.		3600	IN	DS	7250 13 2 A30B3F78B6DDE9A4A9A2AD0C805518B4F49EC62E7D3F4531D33DE697 CDA01CB2
vuejs.org.		3600	IN	DS	2371 13 2 531691EE913F621B688C9AFBE308D422FB3BE59A99A292AF87E3D3F4 43CC1CE4
desec.io.		3600	IN	DS	53307 13 4 156E3DFCCEB69A9B2C4F1C769D9FE8558BFBCF5F0475ABA5DA5924A5 F613C1BE287529D8DA5DF773E573A2A08C69AB99
desec.io.		3600	IN	DS	53307 13 2 3F6A815A28593BA6FF5A3E5DA9B9AF695D8F1022B7E0BDA02793C535 96DA0944

The key tag alone does not identify a domain: cloudflare.com, cloudflare.net and vuejs.org (another Cloudflare-hosted zone) all show key tag 2371, each with a different digest. RFC 4034 computes the digest over the owner name plus the key, so even the same key produces a different DS for each domain. Copy the DS your provider shows for your zone, never one from another domain. desec.io shows that a zone can also publish two digests of one key (digest types 4 and 2). The TTL column matters later: the .com and .net registries publish DS records with 86,400 seconds, while .org and .io used 3,600.

What a broken chain looks like

dnssec-failed.org is a test domain served by Comcast’s name servers whose DS record is wrong on purpose; its digest, decoded below, is a message rather than a hash.

Live capture, 26 September 2026. The same name at 1.1.1.1 with and without checking disabled (+cd), then at 8.8.8.8:

dig @1.1.1.1 dnssec-failed.org A
dig @1.1.1.1 dnssec-failed.org A +cd
dig @8.8.8.8 dnssec-failed.org A
; <<>> DiG 9.10.6 <<>> @1.1.1.1 dnssec-failed.org A
...
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 21359
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; OPT=15: 00 09 6e 6f 20 53 45 50 20 6d 61 74 63 68 69 6e 67 20 74 68 65 20 44 53 20 66 6f 75 6e 64 20 66 6f 72 20 64 6e 73 73 65 63 2d 66 61 69 6c 65 64 2e 6f 72 67 2e ("..no SEP matching the DS found for dnssec-failed.org.")
...

; <<>> DiG 9.10.6 <<>> @1.1.1.1 dnssec-failed.org A +cd
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51150
;; flags: qr rd ra cd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
dnssec-failed.org.	300	IN	A	96.99.227.255
...

; <<>> DiG 9.10.6 <<>> @8.8.8.8 dnssec-failed.org A
...
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 728
...
; OPT=15: 00 09 4e 6f 20 44 4e 53 4b 45 59 20 6d 61 74 63 68 65 73 20 44 53 20 52 52 73 20 6f 66 20 64 6e 73 73 65 63 2d 66 61 69 6c 65 64 2e 6f 72 67 ("..No DNSKEY matches DS RRs of dnssec-failed.org")
...

How to read it:

  • SERVFAIL with no answer is what RFC 4035 prescribes when a validating resolver cannot validate data it expected to be signed. To a browser, this looks the same as a dead DNS server.
  • OPT=15 is an Extended DNS Error (RFC 8914). DiG 9.10.6 does not decode it, so it prints raw bytes. The first two bytes, 00 09, are INFO-CODE 9, DNSKEY Missing: a DS exists at the parent, but no matching key exists in the child. The text after it is each resolver’s own explanation.
  • +cd returns the address. With checking disabled, the resolver hands over the data it would otherwise reject. The record exists; the chain of trust is what is broken. This is the fastest way to tell a DNSSEC failure from a missing record.

Live capture, 26 September 2026. Why validation fails for this domain:

dig @1.1.1.1 dnssec-failed.org DS +short
dig @1.1.1.1 dnssec-failed.org DS +short | awk '{print $4 $5}' | xxd -r -p; echo
dig @1.1.1.1 dnssec-failed.org DNSKEY +cd +multiline +noall +answer | grep "key id"
42069 13 2 62726F6B656E20636861696E206F662074727573742073656E642068 656C7021
broken chain of trust send help!
				) ; ZSK; alg = ECDSAP256SHA256 ; key id = 32784
				) ; KSK; alg = ECDSAP256SHA256 ; key id = 50719

The DS names key tag 42069, the zone’s keys are 32784 and 50719, and the “digest” decodes to an ASCII message. Your own outage will not be this obvious, but it has the same shape: a DS that points at a key your current provider does not have.

Not every resolver validates

Live capture, 26 September 2026. The same broken domain and the signed cloudflare.com through our ISP’s default resolver:

dig @210.220.163.82 dnssec-failed.org A
dig @210.220.163.82 cloudflare.com A +dnssec +noall +comments +answer
; <<>> DiG 9.10.6 <<>> @210.220.163.82 dnssec-failed.org A
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47183
;; flags: qr rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
...
;; ANSWER SECTION:
dnssec-failed.org.	263	IN	A	96.99.227.255
...

; <<>> DiG 9.10.6 <<>> @210.220.163.82 cloudflare.com A +dnssec +noall +comments +answer
...
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
cloudflare.com.		300	IN	A	104.16.132.229
cloudflare.com.		300	IN	A	104.16.133.229
cloudflare.com.		300	IN	RRSIG	A 13 2 300 20260927154707 20260925134707 34505 cloudflare.com. W5j7/7Y3iqEQHQchqp8GSfEZ0Lxyapn/HOLRDPZ0UZn9iB3SPwwLRwTp UtxD2vT80cJStVYqmtTJUvEV5rgWsQ==

This resolver returned an address for the broken domain, and it passed cloudflare.com’s signature through without setting ad: it does not validate. (dig’s warning on the first reply comes from this resolver leaving the ra flag off that response; it answered anyway.)

That cuts both ways for a site owner. Visitors behind non-validating resolvers get no protection from your DNSSEC, and they also do not see your DNSSEC mistakes. A broken DS therefore shows up as “the site works for me” from some people and SERVFAIL from anyone on 1.1.1.1, 8.8.8.8 or a validating ISP.

Where and.guide stands: unsigned, which is a valid state

Live capture, 26 September 2026. Looking for a DS for our own domain, then asking for its address with +dnssec:

dig @1.1.1.1 and.guide DS +dnssec
dig @1.1.1.1 and.guide A +dnssec
; <<>> DiG 9.10.6 <<>> @1.1.1.1 and.guide DS +dnssec
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2053
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1
...
;; AUTHORITY SECTION:
guide.			3600	IN	SOA	v0n0.nic.guide. hostmaster.donuts.email. 1790433050 7200 900 1209600 3600
...
4gskn6mqgok4db5hmf2q9dk5lk75nr3o.guide.	3600 IN	NSEC3 1 1 0 73 4J7EL1MFRS1T2UDSMT3T4LRVVUM5RGF9  NS DS RRSIG
...
coa0vaq2vtpst74nonfu1e1f368i8ebo.guide.	3600 IN	NSEC3 1 1 0 73 CPMLMM2UR01DPL704V9G2IM6K1SR481P  NS SOA RRSIG DNSKEY NSEC3PARAM
...

; <<>> DiG 9.10.6 <<>> @1.1.1.1 and.guide A +dnssec
...
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
...
;; ANSWER SECTION:
and.guide.		120	IN	A	172.66.44.244
and.guide.		120	IN	A	172.66.47.12
...

There is no DS for and.guide. The .guide zone is signed, and its NSEC3 records are the signed proof that no DS exists. The A answer comes back without ad and without signatures, and our Cloudflare name servers return no DNSKEY for the zone at all: DNSSEC is not enabled for and.guide.

The registry agrees. RDAP returns the registry’s record for a domain, including whether the delegation is signed:

for d in and.guide cloudflare.com; do
  printf "%-15s " $d
  curl -sL https://rdap.org/domain/$d | jq -c '[.secureDNS.delegationSigned, [.secureDNS.dsData[]?.keyTag]]'
done
and.guide       [false,[]]
cloudflare.com  [true,[2371]]

The same RDAP record lists Cloudflare, Inc as and.guide’s registrar. RFC 4035 gives resolvers four ways to classify an answer, and our captures cover three of them:

State Meaning What a validating resolver returns Example above
Secure Signed chain from the root down to the answer Answer with ad cloudflare.com
Insecure Provably no chain (no DS at the parent) Answer without ad and.guide
Bogus A chain should exist but does not validate SERVFAIL dnssec-failed.org
Indeterminate The resolver cannot get the DNSSEC records it needs Depends on the resolver Not captured

Insecure is not an error. It is the state of every domain that has not turned DNSSEC on.

How missing names look in a signed zone

Signed zones also have to prove that a name does not exist, and Cloudflare does it in a way that changes what you see.

Live capture, 26 September 2026. A random, nonexistent name under cloudflare.com, asked of Cloudflare’s authoritative server with and without +dnssec, then of 1.1.1.1:

dig @ns3.cloudflare.com andguide-neg-xl064m.cloudflare.com A +norec +dnssec +noall +comments +authority
dig @ns3.cloudflare.com andguide-neg-xl064m.cloudflare.com A +norec +noall +comments +authority
dig @1.1.1.1 andguide-neg-xl064m.cloudflare.com A +noall +comments
; <<>> DiG 9.10.6 <<>> @ns3.cloudflare.com andguide-neg-xl064m.cloudflare.com A +norec +dnssec +noall +comments +authority
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25822
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
...
;; AUTHORITY SECTION:
cloudflare.com.		300	IN	SOA	ns3.cloudflare.com. dns.cloudflare.com. 2415557203 10000 2400 604800 300
andguide-neg-xl064m.cloudflare.com. 300	IN NSEC	\000.andguide-neg-xl064m.cloudflare.com. RRSIG NSEC TYPE128
...

; <<>> DiG 9.10.6 <<>> @ns3.cloudflare.com andguide-neg-xl064m.cloudflare.com A +norec +noall +comments +authority
...
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 42554
...

; <<>> DiG 9.10.6 <<>> @1.1.1.1 andguide-neg-xl064m.cloudflare.com A +noall +comments
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4937
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
...

With DNSSEC requested, the authoritative server answered NOERROR with a single NSEC record claiming the name exists with no data. That is compact denial of existence (RFC 9824); TYPE128 is the NXNAME marker, which DiG 9.10.6 has no name for. Without +dnssec, the same server said NXDOMAIN. Through 1.1.1.1 the reply was a validated NOERROR with an empty answer even though that query did not ask for DNSSEC records; the same query with +dnssec, at 1.1.1.1 and at 8.8.8.8, also came back NOERROR. If you are waiting for a new name in a signed Cloudflare zone, look for an empty answer with an SOA rather than for NXDOMAIN; the negative caching guide explains how long those answers are cached.

The outage to avoid: a DS left behind after a DNS move

Suppose a signed domain moves from provider A to provider B, and the registrar still publishes A’s DS. Validating resolvers fetch that DS from the parent, look for a matching key at provider B, and find none: the same DNSKEY Missing failure as dnssec-failed.org, for every name in the domain. Visitors on non-validating resolvers keep working, which makes the first reports confusing.

The fix is also slow. Resolvers keep the stale DS for the parent’s DS TTL, which is a full day under .com and .net. RFC 9520 separately requires resolvers to cache resolution failures, for between 1 second and 5 minutes, so each resolver keeps failing for a while even after the chain is repaired.

The safe order, which Cloudflare documents for bringing a signed domain onto Cloudflare and which applies in any direction:

  1. Remove the DS record at the registrar. Keep signing at the old provider for now.
  2. Wait until dig DS example.com no longer shows it, then wait out the old DS TTL. Cloudflare’s docs say to expect 24 to 48 hours for most TLDs; the DS TTLs we saw ranged from one hour (.org, .io) to one day (.com, .net).
  3. Change the name servers, and wait for the old NS TTL.
  4. Enable DNSSEC at the new provider and add its DS at the registrar.

That order leaves the domain unsigned (insecure) for a day or two, which is safe. The alternative is a multi-signer migration, where both providers serve each other’s signing keys during the move. Cloudflare supports it when the old provider lets you add DNSKEY records, and its guide says to wait at least one and a half times the old DS TTL before removing the old provider’s DS. If you are moving onto Cloudflare, the Cloudflare DNS setup guide covers the rest of the move.

What a site owner actually has to decide

What you gain: resolvers that validate (1.1.1.1 and 8.8.8.8 did in our tests) can reject forged answers for your names. Since 15 March 2026, CA/Browser Forum Ballot SC-085v2 also requires public CAs to validate DNSSEC, when it is present, for CAA and domain-validation lookups. A signed zone protects certificate issuance from spoofed DNS, and a broken chain can block issuance as well as page loads; the CAA guide covers the CAA side. What you do not gain: DNSSEC provides no confidentiality, so DNS traffic is exactly as visible as before (RFC 4033 says so explicitly), and it does nothing for visitors whose resolver does not validate.

Your situation What it means in practice
Registrar and DNS at the same provider (and.guide: Cloudflare Registrar and Cloudflare DNS) Enabling is a setting. Cloudflare says it submits the DS automatically for Cloudflare Registrar domains, which can take one to two days. The ongoing cost is handling the DS before any future DNS move.
Registrar separate from the DNS host You copy the key tag, algorithm, digest type and digest into the registrar yourself. Cloudflare signs with algorithm 13; its docs note that some registrars call it ECDSA Curve P-256 with SHA-256.
A DNS provider change is planned soon Move first, sign afterwards. If you are already signed, follow the order above or a multi-signer migration.
Two providers serve the zone at once Needs multi-signer DNSSEC support on both sides.
Nobody can reliably log in to the registrar Fix that before signing. The DS is the record you may need to remove in a hurry.

Checks after enabling DNSSEC, or before moving

dig +short DS example.com                                  # what the parent publishes
dig @<one-of-your-NS-hosts> example.com DNSKEY +multiline  # key ids your provider serves
dig @1.1.1.1 example.com A +dnssec | grep flags            # look for "ad"
dig @1.1.1.1 example.com A +cd                             # only if you get SERVFAIL

The DS key tag should match a key id marked KSK, a validating resolver should show ad, and a SERVFAIL that disappears with +cd points at the chain rather than the record. The DNS lookup tool shows the AD flag from Cloudflare’s and Google’s resolvers side by side, which is a quick second opinion after you add or remove a DS.