SOA and Serial Numbers

SOA and serial numbers

Every DNS zone has exactly one SOA record. SOA stands for Start of Authority, and it carries metadata about the zone — who runs it, when it last changed, and how secondary nameservers should behave. Most techs ignore SOA records. They shouldn’t, because the serial number is the cleanest signal you have for “is this zone in sync.”

What’s in an SOA record

A typical SOA for isidoregroup.com:

dig isidoregroup.com SOA
;; ANSWER SECTION:
isidoregroup.com. 3600 IN SOA ns11.domaincontrol.com. dns.jomax.net. 2024051301 28800 7200 604800 600

Seven fields after the SOA. In order:

  1. mname — primary authoritative nameserver. ns11.domaincontrol.com. here. This is the master copy of the zone; other authoritative servers pull from it.
  2. rname — administrative contact email, with @ rewritten as .. dns.jomax.net. reads as dns@jomax.net. Often a generic mailbox at the DNS host.
  3. serial — version number for the zone. 2024051301 here. Increments on every change.
  4. refresh — how often secondary servers should check the primary for changes. 28800 seconds = 8 hours.
  5. retry — wait time if a refresh fails. 7200 = 2 hours.
  6. expire — how long a secondary will keep serving the zone if it can’t reach the primary. 604800 = 1 week.
  7. minimum — historically the default TTL, today used for negative-response caching (how long resolvers cache “this name doesn’t exist”). 600 = 10 minutes.

What Cathedra checks

DnsHygieneCheck calls dns_get_record($domain, DNS_SOA). If the result is empty, you get:

status: warning / severity: low
“No SOA record returned for {domain}.”

This is unusual on a healthy zone — authoritative servers always return an SOA when asked. A missing SOA usually means the recursive resolver couldn’t reach the authoritative server at all, or the zone is malformed.

When the SOA returns normally, Cathedra returns:

status: pass
“SOA present. Primary NS: {mname}, serial: {serial}.”

That’s the entire SOA check in Cathedra: presence plus an informational line showing the primary nameserver and the current serial. The check doesn’t validate the serial format or compare across servers — that’s your job during debugging.

The serial number — the field you’ll actually use

The serial is a monotonically increasing integer. Every authoritative DNS host has its own way of generating it, but two common patterns dominate:

Date-based serial: YYYYMMDDNN — year, month, day, two-digit counter. 2024051301 means “1st change on May 13, 2024.” If you make another change the same day, it becomes 2024051302. Most DNS hosts use this format. It’s human-readable and self-documenting.

Unix timestamp serial: A plain Unix epoch time, like 1715616423. Cloudflare and a few cloud DNS providers use this. Less readable but guaranteed unique.

The exact format doesn’t matter to DNS — only that the number increases. If the new serial is lower than the old serial, secondary servers refuse to pull the new zone (they think it’s stale). This is why hand-editing zone files in the past sometimes broke replication.

Using the serial to detect drift

If a domain has multiple authoritative nameservers, all of them should return the same serial. Query each directly:

dig @ns11.domaincontrol.com isidoregroup.com SOA +short
ns11.domaincontrol.com. dns.jomax.net. 2024051301 28800 7200 604800 600

dig @ns12.domaincontrol.com isidoregroup.com SOA +short
ns11.domaincontrol.com. dns.jomax.net. 2024051301 28800 7200 604800 600

Same serial: zones are in sync. Different serials: the secondary hasn’t pulled the latest update from the primary yet. Wait a refresh interval and check again. If the serials still disagree, replication is broken.

This is also how you confirm a DNS change has actually published. Make the edit in the registrar’s control panel, then query the authoritative directly and look at the serial. If it incremented, the zone was updated. If it didn’t, the change was queued but not committed — usually a control-panel quirk where you forgot to hit a final “publish” button.

What mname tells you about the architecture

The mname field names the primary authoritative server — the one secondaries pull from. For most managed DNS hosts (GoDaddy, Cloudflare, Route53), mname is one of the public nameservers the registrar published. For self-hosted or hidden-primary setups, mname may point to a server that isn’t listed in NS records at all. That’s legal and common in enterprise setups.

For our work, mname is mostly informational. You’ll use it during incident triage when a zone update isn’t propagating — you query the mname directly to confirm the master copy actually has the change.

Cheat sheet

Field What it tells you
mname Primary authoritative server (the master)
rname Admin contact email (@ written as .)
serial Zone version number — increments on every change
refresh How often secondaries poll the primary
retry Retry interval if refresh fails
expire How long secondaries serve a stale zone if the primary is unreachable
minimum Negative-response cache TTL

What you should remember

  • Cathedra’s SOA check is presence-only. Pass returns “SOA present. Primary NS: {mname}, serial: {serial}.” Missing SOA is a warning / low and almost always points to a resolver or zone problem.
  • The serial is the most useful field. It increments on every change. Use it to confirm a DNS edit actually published, and to compare authoritative servers for replication drift.
  • Date-based serials (YYYYMMDDNN) are the dominant format. Cloudflare-style epoch serials are valid but less common.
  • Query each NS host directly with @nameserver to compare serials when you suspect replication problems.
  • mname names the primary master, which may or may not be one of the public NS records.

Next lesson: CAA records — what they restrict, why missing ones are info-only, and when adding them is worth the time.


Cathedra alignment: DnsHygieneCheck — SOA Record