A single zone on your BIND secondary starts returning SERVFAIL. Other zones on the same server answer normally. The named process is up, CPU and memory look fine, and port 53 responds to health checks. Your monitoring shows green because it checks process liveness or queries a different zone. Only clients asking for that one zone are failing.
This is the end state of the zone staleness cascade. Transfers from the primary have been failing silently for days or weeks while the secondary kept serving the last-known-good data. The SOA expire timer counted down to zero, and BIND removed the zone from its database. The transition is binary: at one moment the zone works (stale but functional), at the next it is gone. Recovery requires a full AXFR, and that transfer must succeed or the cycle repeats.
What this means
The SOA record’s expire field defines how long a secondary may serve zone data after the last successful transfer from the primary. BIND counts down from that value every time a refresh or retry attempt fails. When the countdown reaches zero, BIND removes the zone from its authoritative database and stops answering queries for it. Clients receive SERVFAIL .
Key characteristics of this failure:
- Zone-scoped, not server-scoped. Only the expired zone breaks. All other zones, recursive resolution (if enabled), and the
namedprocess itself continue normally. - Long silent period before failure. A zone with a 7-day or 41-day expire timer can serve stale data for that entire window with no errors and no log complaints beyond quiet transfer retry messages.
- Binary cliff. There is no degraded mode between “serving stale data” and “zone gone.” The transition is instantaneous.
- Recovery needs a full AXFR. Once the zone is expired and removed, the secondary cannot use IXFR to catch up. It must transfer the entire zone from scratch.
BIND enforces constraints on the expire value regardless of what the primary advertises in its SOA. The expire is capped at a hard-coded maximum of 14,511,600 seconds (24 weeks). It is also floored at the sum of refresh and retry values, each of which has a 5-minute minimum.
flowchart TD
A["Primary reachable, transfers succeed"] --> B["Transfer starts failing"]
B --> C["Secondary serves stale data"]
C --> D["SOA expire countdown ticking"]
D --> E{"Expire reached?"}
E -->|No, transfer recovers| A
E -->|Yes| F["Zone removed, SERVFAIL"]
F --> G["Full AXFR required"]
G --> ACommon causes
| Cause | What it looks like | First thing to check |
|---|---|---|
| Primary decommissioned or IP changed | Transfer logs show connection refused or timeout; primary not at old address | dig @primary-ip <zone> SOA +short from the secondary |
| Firewall blocks TCP/53 between primary and secondary | UDP queries to primary work; AXFR/IXFR times out | dig @primary-ip <zone> AXFR from the secondary host |
| TSIG key mismatch | Transfer denied; xfer-in logs show “bad signature” or TSIG errors | Compare key statements in named.conf on both sides |
| Primary overloaded | Intermittent transfer failures; transfers succeed during low-traffic periods | Check primary’s CPU, FD usage, and TCP connection count |
| Disk full on secondary | Transfer completes but write fails; xfer-in logs show I/O error | df -h on the partition holding zone and journal files |
Quick checks
Safe, read-only commands. Run them on the affected secondary.
# Check the zone's current state and expire countdown
rndc zonestatus example.com
# Compare SOA serials between primary and secondary
dig @primary-ip example.com SOA +short
dig @127.0.0.1 example.com SOA +short
# Query the zone directly to confirm SERVFAIL
dig @127.0.0.1 example.com SOA +time=2 +tries=1
# Check for transfer failure and expiry log messages
journalctl -u named --since "7 days ago" | grep -i "example.com.*transfer\|example.com.*expired\|xfer-in"
# Verify TCP connectivity to the primary on port 53
dig @primary-ip example.com SOA +tcp +time=3 +tries=1
# Check disk space on the partition holding zone files
df -h /var/named
# Confirm total loaded zones (process is fine, just one zone missing)
rndc status | grep -i "zones"
How to diagnose it
Confirm the zone is expired. Run
rndc zonestatus <zone>. If the zone is expired or not loaded, the output shows an error or the “expires” field is in the past. The log linezone <zone>/IN: expiredconfirms it.Verify only that zone is broken. Query a different zone hosted on the same secondary. If other zones answer normally, the problem is zone-scoped transfer failure, not a server-wide issue.
Check primary reachability from the secondary. Run
dig @primary-ip <zone> SOAfrom the secondary’s host. If this times out, the problem is network reachability. If it returns REFUSED or SERVFAIL, the primary itself may be broken.Test the transfer path directly. Run
dig @primary-ip <zone> AXFRfrom the secondary. If this fails, the transfer ACL, TSIG key, or TCP path is broken. If it succeeds, the zone can be recovered withrndc retransfer <zone>.Review transfer failure history. Search xfer-in logs for the timeline of when transfers started failing. This tells you how long the zone has been stale and helps identify the triggering event (firewall change, key rotation, primary migration).
Check whether a restart already masked the problem. Restarting
namedresets the expire timer if the zone file still exists on disk. The secondary reloads the old data and resumes serving it, buying time but not fixing the underlying transfer failure. If someone restartednamedrecently, the zone may appear healthy now but will expire again after the full SOA expire duration unless the transfer path is fixed.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
| SOA expire runway | The actual countdown to outage, not just serial lag | Runway below 25% of expire value or below 24 hours |
| SOA serial mismatch (primary vs secondary) | Earliest indicator that transfers are failing | Mismatch persisting beyond the refresh interval |
| Transfer success/failure rate (xfer-in logs) | Shows the mechanism that feeds the zone is broken | Repeated transfer timeout or denial entries |
| Zone-specific SERVFAIL | The user-visible symptom once expiry hits | SERVFAIL limited to one zone, zero for others |
rndc zonestatus expires field | Authoritative local source for when the zone will die | “expires” timestamp within 24 hours or in the past |
| Primary reachability from secondary | The upstream dependency that feeds the timer | Connection refused, timeout, or wrong serial from primary |
Fixes
Primary unreachable or decommissioned
If the primary has been decommissioned or its address changed without updating the secondary’s masters (or primaries in BIND 9.18+ terminology) statement, no transfer will ever succeed.
- Fix: Update the
masters/primariesaddress in the secondary’s zone configuration. Then runrndc retransfer <zone>to force an immediate full transfer. - Tradeoff: If the primary is permanently gone and no other source exists, rebuild the zone data from a backup or from another secondary that still has a valid copy.
Firewall blocks TCP/53
Zone transfers use TCP. A firewall rule that permits UDP/53 but blocks TCP/53 between the secondary and primary will break transfers while allowing SOA queries to succeed.
- Fix: Open TCP/53 between the secondary and primary in both directions. Verify with
dig @primary-ip <zone> AXFRfrom the secondary host. - Tradeoff: If your security policy restricts TCP/53 broadly, consider a dedicated transfer network, a VPN tunnel, or an intermediate hidden primary that the secondaries can reach.
TSIG key mismatch
TSIG keys used for transfer authentication can drift if one side is updated but not the other. The secondary’s transfer request fails authentication, and BIND logs a signature or TSIG error in the xfer-in category.
- Fix: Copy the current key from the primary to the secondary (or vice versa), ensure the
allow-transferandmasters/primariesstatements reference the same key, reload the configuration, and runrndc retransfer <zone>. - Tradeoff: Key rotation procedures should update all secondaries atomically. Running both old and new keys temporarily during the transition window avoids a gap.
Disk full on the secondary
If the secondary cannot write the received zone data or its journal file, the transfer completes over the network but the write fails. BIND logs an I/O error.
- Fix: Free disk space on the affected partition. Then run
rndc retransfer <zone>. - Tradeoff: If the disk filled due to unbounded
named_stats.txtgrowth from repeatedrndc statscalls, add log rotation or truncate the file.
Forcing recovery after expiry
Once the zone is expired and removed, the only path to recovery is a successful full AXFR. The secondary requests IXFR by default, but with the zone missing from memory it falls back to AXFR.
# Force a full transfer of the expired zone
rndc retransfer example.com
# Verify the zone loaded successfully
rndc zonestatus example.com
# Confirm queries now succeed
dig @127.0.0.1 example.com SOA +short
If the transfer fails again, the zone remains unserved. Fix the transfer path first.
Prevention
Monitor SOA expire runway, not just serial mismatch. Serial mismatch tells you transfers are failing; expire runway tells you when the zone will actually break. Alert when runway drops below 25% of the expire value or below 24 hours, whichever is shorter. The
rndc zonestatus <zone>output includes the “expires” timestamp for this purpose.Track serial consistency between primary and all secondaries. A SOA serial comparison catches transfer failures within minutes rather than days. Query the SOA record against each server and compare the serial field.
Use
dig +expirefor remote expire monitoring. BIND 9.10+ supports the EDNS EXPIRE option, which lets you query a secondary’s remaining expire time remotely withoutrndcaccess. Useful for monitoring secondaries you do not control directly.Validate the transfer path after any firewall or network change. Run
dig @primary-ip <zone> AXFRfrom each secondary to confirm TCP/53 works end to end. Do not assume that successful UDP SOA queries mean transfers will work.Alert on xfer-in failures. BIND logs every transfer attempt in the xfer-in category. A sustained stream of failures is the earliest indicator that the expire countdown has started. Forward these logs to your monitoring system.
Remember that restarting
namedresets the timer. If the zone file is still on disk, restartingnamedreloads the old data and resets the expire countdown. This can mask an ongoing transfer failure for another full expire duration. Never treat a restart as a fix.
How Netdata helps
SOA expire runway as a first-class signal. Netdata collects zone-level statistics from BIND’s statistics channel and can surface the expire countdown as a trendable metric, turning a cliff-edge failure into something you can see coming days in advance.
Serial mismatch correlation. By comparing SOA serials between primary and secondary at regular intervals, Netdata can alert on divergence before the expire countdown becomes critical.
Zone-scoped SERVFAIL detection. Netdata’s per-second query metrics can show SERVFAIL rising for one specific zone while other zones remain clean, narrowing the problem from “DNS is broken” to “this zone is expired.”
Transfer failure signal correlation. BIND’s zone transfer counters and xfer-in log streams, when correlated with expire runway trends, expose the full causal chain: transfer failures start, serial diverges, runway shrinks, zone expires.
Process health in context. Netdata shows
namedprocess liveness, memory, CPU, and file descriptor usage alongside zone health. When only one zone is expired, the process metrics stay green, which is itself diagnostic: the server is fine, the transfer path is not.
Related guides
- BIND cache eviction storms: DeleteLRU, an undersized max-cache-size, and the pressure spiral
- BIND cache hit ratio dropping: the leading edge of recursive pain
- BIND clients-per-query and max-clients-per-query: duplicate recursion for popular names
- BIND forwarding loops: recursion that never terminates and burns recursive slots
- How BIND actually works in production: a mental model for operators
- BIND lame delegations: ’lame server resolving’ and nameservers that are not authoritative
- BIND monitoring checklist: the signals every production resolver and authoritative server needs
- BIND monitoring maturity model: from survival to expert
- BIND ’no more recursive clients: quota reached’: the recursive-clients circuit breaker
- named not responding on port 53: total outage versus UDP-works-TCP-fails
- BIND resolver NumFetch per view: per-view recursive pressure in split-horizon setups
- BIND NXDOMAIN spike: DGA malware, water torture, and Windows suffix search lists






