SOA: start of authority
Required at every zone apex. Exactly one per zone. SOA holds the zone's metadata: who runs it, the serial number that drives secondary refresh, and the timers that govern zone transfer behavior.
In one line:
example.com. SOA ns1.example.com. admin.example.com. 2026072601 ...
└── this zone ┘ └type┘ └── primary ───┘ └── contact ─────┘ └── version| Type number | 6 |
| RFC | 1035 |
| RDATA | Primary NS · admin email · serial · refresh · retry · expire · minimum |
What it holds#
Seven fields, in this order on the wire:
isitdns.net. SOA coleman.ns.cloudflare.com. dns.cloudflare.com.
2412230330 10000 2400 604800 1800The zone
isitdns.netis administered fromcoleman.ns.cloudflare.com, its contact isdns@cloudflare.com(the first dot stands in for the @), and the serial number is the zone's version counter: it goes up every time anything changes.
Fields in order: primary NS, admin email, serial, refresh, retry, expire, minimum. The serial advances every time the zone is edited, so the live value will differ from the snapshot above.
| Field | Meaning |
|---|---|
| Primary NS | The "MNAME": the master server. Secondaries refresh from this name. |
| Admin email | Contact for the zone, encoded with . instead of @ (dns.cloudflare.com. encodes dns@cloudflare.com). A . already in the local part must be escaped: John.Smith@widget.xx becomes John\.Smith.widget.xx (RFC 1912 section 2.2). |
| Serial | A monotonically increasing integer secondaries use to detect changes. Conventional format: YYYYMMDDNN. |
| Refresh | How often secondaries poll the primary for serial changes. Mostly superseded by NOTIFY (RFC 1996). |
| Retry | If a refresh fails, how long to wait before retrying. |
| Expire | If the primary stays unreachable, how long before secondaries stop serving stale data. |
| Minimum | How long resolvers may cache negative answers (NXDOMAIN and NODATA) from this zone (RFC 2308 negative-cache TTL). See negative caching and TTL. |
When to use it#
Nobody chooses to use SOA. Every zone gets exactly one at the apex when the zone is created; managed DNS providers auto-generate it, and in a self-hosted zone file (BIND, NSD) you write it once. Using SOA means reading it:
- Serial checks. Ask each authoritative server for the zone's SOA and compare serials; a server whose serial is behind is serving a stale copy. The paired
digcommands below do exactly this. - Transfer debugging. When zone transfer between primary and secondaries breaks, the serial mismatch is the symptom.
- Negative-cache tuning. The minimum field is the one field worth editing by hand: a long minimum means
NXDOMAINresponses hang around in resolvers long after you add the record. Pull minimum down before adding records that previously did not exist.
When not to use it#
- Not a propagation signal for resolvers. The serial tells secondaries when to transfer; resolver caches expire answers on each record's own TTL (RFC 1035 section 3.2.1) and never consult the serial. Bumping the serial flushes nobody's cache.
- Not the zone's default TTL. The minimum field set default TTLs under original RFC 1035; RFC 2308 section 4 redefined it as the negative-cache TTL and gave zone files the
$TTLdirective for the default instead. - Not a reliable contact address. The admin email is whatever the operator set, and managed zones carry the provider's default (
dns@cloudflare.comabove), not the zone owner's mailbox.
dig example#
example.isitdns.net is a set of names inside the isitdns.net zone, not a zone of its own: there is no zone cut, so it has no SOA. The live example is the apex, isitdns.net.
dig @1.1.1.1 isitdns.net SOA +shortcoleman.ns.cloudflare.com. dns.cloudflare.com. 2412230330 10000 2400 604800 1800The serial advances each time the zone is edited, so the live value will differ from the snapshot above.
nslookup ships on Windows and macOS and shows the same fields in a labeled layout, so it works where dig is not installed:
nslookup -type=SOA isitdns.net 1.1.1.1Server: 1.1.1.1
Address: 1.1.1.1#53
Non-authoritative answer:
isitdns.net
origin = coleman.ns.cloudflare.com
mail addr = dns.cloudflare.com
serial = 2412230330
refresh = 10000
retry = 2400
expire = 604800
minimum = 1800
Authoritative answers can be found from:The dangling
Authoritative answers can be found from:line with nothing under it is normal.
The serial in the answer is the heartbeat of zone state: if two nameservers disagree, the one whose serial is behind per RFC 1982 serial arithmetic is stale. A numerically lower serial is not always the older one. Near a 32-bit wraparound, the numerically higher value can be the stale copy.
To compare, ask each authoritative server directly:
dig @coleman.ns.cloudflare.com isitdns.net SOA +short
dig @hera.ns.cloudflare.com isitdns.net SOA +shortcoleman.ns.cloudflare.com. dns.cloudflare.com. 2412230330 10000 2400 604800 1800
coleman.ns.cloudflare.com. dns.cloudflare.com. 2412230330 10000 2400 604800 1800Both return the same serial, so both are serving the same version of the zone. A lagging server returns a lower serial and is serving a stale copy. The MNAME field stays coleman in both answers: it names the primary, not the server you asked.
For an internal zone you control, query your authoritative server directly:
dig @PRIMARY_IP example.internal SOAnslookup -type=SOA example.internal PRIMARY_IP
PRIMARY_IPandexample.internalare placeholders. Neither resolves publicly. Substitute your own authoritative server address and zone name; these commands return no answer as written.
nslookup cannot show EDNS options, DNSSEC bits, or the AD flag. Use dig for those.
See it live: isitdns.net SOA on the front-page dig tool
The RFC: SOA is defined in RFC 1035 section 3.3.13. The minimum field was redefined as the negative-cache TTL by RFC 2308 section 4.
DoH query (HTTPS)#
DoH is DNS-over-HTTPS. The JSON wire format uses application/dns-json (a Cloudflare/Google convention; RFC 8484 uses binary DNS-wire-format instead):
curl -s -H 'accept: application/dns-json' \
'https://cloudflare-dns.com/dns-query?name=isitdns.net&type=SOA' \
| jq .Answer[
{
"name": "isitdns.net",
"type": 6,
"TTL": 1800,
"data": "coleman.ns.cloudflare.com. dns.cloudflare.com. 2412230330 10000 2400 604800 1800"
}
]nslookup cannot do DoH/DoT/DoQ. On Windows,
Resolve-DnsNameuses the system-configured DoH resolver when the OS is set up for encrypted DNS; there is no-DnsOverHttpsparameter and it does not accept an arbitrary endpoint as-Server. To probe a specific DoH endpoint, use thecurlexample above.
Gotchas#
- Serial number rollover. SOA serial is a 32-bit unsigned int governed by RFC 1982 serial-number arithmetic. Use
YYYYMMDDNN(the RFC 1912 section 2.2 recommendation, good until year 4294) for predictability and you will never hit it. Use a hand-tracked counter and someday you will. - Long minimum bites. A zone with
minimum = 86400(a day) means anNXDOMAINyou cached this morning is still cached when you fix the record this afternoon. Lower it before making schema-style changes; raise it back later. Per RFC 2308 section 5, the actual negative cache TTL used by resolvers ismin(minimum, SOA record TTL), so droppingminimumbelow the SOA record's own TTL does shorten negative caching. What buys you nothing is raisingminimumabove that TTL: the SOA record's TTL is the ceiling, and lowering both is the way to lower the answer. - Multiple SOAs. RFC 1035 section 5.2 says exactly one SOA RR should be present at the top of the zone. Most authoritative servers refuse to create a second. But if you import a zone file with two SOAs by accident, behavior is undefined and embarrassing.
- Cloudflare-managed zones. Cloudflare auto-generates the SOA, but the fields (MNAME, admin email, refresh, retry, expire, minimum, and the SOA record's own TTL) are tunable per zone via the DNS settings API or account-wide via DNS zone defaults. The serial is the exception: Cloudflare manages it internally, and it is an opaque counter (
2412230330in the snapshot above), notYYYYMMDDNN.