A BIND secondary serving stale data is not broken. It answers queries with old but functional records, and from the outside it looks healthy. The danger is the countdown underneath: the SOA expire timer, ticking from the last successful zone transfer. When it reaches zero, the secondary stops serving the zone and returns SERVFAIL or REFUSED for every query against it.

Most teams monitor SOA serial consistency between primary and secondary. That catches “the secondary is behind” but not how much time remains before it gives up entirely. The expire runway does. It degrades over hours to days, making it ideal for early warning. It is the difference between catching a transfer failure with days of runway and discovering it after the zone has expired and clients are failing.

What it is and why it matters

Every DNS zone has an SOA record. The last four fields control secondary transfer and expiry behavior:

FieldMeaningTypical value
refreshHow often the secondary checks the primary for a new serial3600 to 86400 seconds
retryWait time before retrying after a failed refresh600 to 3600 seconds
expireMaximum time the secondary serves the zone without a successful transfer604800 to 1209600 seconds (1 to 2 weeks)
minimumDefault negative TTL, also used for zone caching86400 seconds

The expire value defines how long a secondary continues serving a zone without a successful transfer. Once the elapsed time since the last successful transfer exceeds expire, the secondary removes the zone from its active set and stops answering.

Serial mismatch tells you the secondary is behind. Expire runway tells you when it gives up. A secondary one hour into a seven-day expire window is behind but fine. A secondary six days into a seven-day window is one day from dropping the zone.

How it works

BIND tracks the time of the last successful zone transfer (AXFR or IXFR) and compares it against the SOA expire value:

time_remaining = SOA_expire - time_since_last_successful_transfer

Read this directly from rndc zonestatus on the secondary:

rndc zonestatus example.com

The output includes an expires: field showing the absolute time when the zone will expire if no successful transfer occurs before then.

To compute the runway manually, query the SOA to get the expire value:

# SOA fields: mname rname serial refresh retry expire minimum
dig @secondary-ip example.com SOA +short

The sixth field is expire in seconds. Note that dig gives you the configured expire value, not the time of the last transfer. To compute remaining runway you also need the last successful transfer timestamp, which comes from rndc zonestatus, BIND’s xfer-in log category, or the zone file modification time on the secondary’s filesystem.

The runway resets to full on every successful transfer. A secondary that transfers successfully every refresh interval never approaches the cliff. The runway only matters when transfers start failing.

flowchart TD
    A[Successful transfer] --> B[Serving zone
runway = SOA expire] B --> C{Refresh interval fires} C -->|Serial changed, transfer OK| B C -->|No serial change| B C -->|Transfer fails| D[Retry per SOA retry interval] D -->|Transfer succeeds| B D -->|Transfer fails again| E{Expire runway
exhausted?} E -->|No, runway remains| D E -->|Yes, elapsed time
exceeds expire| F[Zone expired
secondary returns SERVFAIL] F -->|Primary reachable again| G[Full AXFR required
IXFR not sufficient] G --> B

Once the expire timer fires, the zone transitions to expired. Recovery requires a full AXFR; an incremental IXFR is not sufficient.

Where it shows up in production

Hidden primary with public secondaries. The primary is not in the NS records and receives no direct queries. If it goes down or becomes unreachable, every secondary starts counting down. The zone resolves for days, then all secondaries expire in sequence.

Cascading secondaries. A secondary transfers from another secondary rather than from the primary. If the upstream is stale or expired, the downstream may inherit incorrect expiration data. BIND’s request-expire option (default yes) enables the EDNS EXPIRE option on outgoing queries, letting a downstream secondary learn the upstream’s actual expiration timer. Without this, a cascading secondary may set its expire timer incorrectly.

Firewall or network changes. A rule change that blocks TCP port 53 between primary and secondary stops transfers immediately. The secondary continues serving stale data until expire. The failure is invisible because the secondary still answers queries with old data.

TSIG key rotation. If you rotate the TSIG key for zone transfers but only update one side, transfers fail silently. The secondary counts down while the primary is healthy and reachable.

Primary decommissioned without cleanup. The primary is shut down or repurposed. Secondaries keep serving from their last transfer. After expire runs out, the zone disappears from all secondaries simultaneously.

What you cannot override on the secondary

BIND provides clamping options for refresh and retry timers: min-refresh-time, max-refresh-time, min-retry-time, max-retry-time. There are no equivalent options for expire. A secondary must honor the SOA expire value from the primary.

BIND does enforce internal bounds on the expire value regardless of the SOA record:

  • The minimum effective expire is refresh + retry, with each floored at 300 seconds. A zone never expires in less than approximately 10 minutes, even if the SOA claims expire 0.
  • The maximum effective expire is 14515200 seconds (24 weeks).

You cannot extend a zone’s expire on the secondary side. If the primary publishes a dangerously short expire, the only fix is to change the SOA record on the primary.

Alerting and thresholds

The expire runway is a countdown, not a binary signal. Alert on the percentage of runway remaining, not a fixed time threshold alone.

Runway remainingSeverityAction
Above 50%INFOTrack for trending
Below 50%TICKETInvestigate transfer failure; runway is shrinking
Below 25% or below 24 hours (whichever is shorter)PAGEZone is at risk; fix transfers now

The “whichever is shorter” rule matters for zones with extreme expire values. A zone with a 1-hour expire at 25% has 15 minutes left. A zone with a 41-day expire at 25% has over 10 days. The 24-hour floor ensures at least one day to respond for long-expire zones; the 25% threshold catches short-expire zones early.

Cold-start gating

A newly configured secondary may show a low or unknown runway before the initial transfer completes. Gate the alert on whether the secondary has successfully served the zone before:

  • Only alert on zones where the secondary has a valid serial and has completed at least one successful transfer.
  • Suppress alerts for zones that have never transferred successfully. They are in initial provisioning, not failure.

This prevents paging during the window between adding a zone to the secondary’s configuration and the first successful AXFR.

What happens at expiry

When the expire timer fires, BIND logs a message in the general category following the pattern zone <zone>/IN: expired. The secondary stops answering queries for that zone, returning SERVFAIL or REFUSED. Other zones on the same server continue normally. The server itself looks healthy: most queries succeed, and only queries for the expired zone fail.

Recovery requires a full AXFR. Once the primary is reachable and the transfer succeeds, the runway resets.

# Force a full zone transfer on the secondary.
# Can be resource-intensive for large zones transferred over slow links.
rndc retransfer example.com

Use after resolving whatever prevented transfers from succeeding.

Signals to watch in production

SignalWhy it mattersWarning sign
SOA expire runway (from rndc zonestatus)Direct countdown to zone expiryRunway below 50% of SOA expire value
SOA serial mismatch (primary vs secondary)Early indicator that transfers are failingSecondary serial behind primary for longer than refresh interval
Transfer log entries (xfer-in category)Shows transfer attempts, failures, and successRepeated failures with no success entries
Primary reachabilityRoot cause of most expire countdownsdig @primary <zone> SOA timing out or returning wrong serial
Per-zone SERVFAIL rateConfirms the zone has already expiredSERVFAIL for a specific zone only, not across all queries

Expire runway is the leading indicator. Serial mismatch is the early warning. SERVFAIL for the zone confirms it has already expired. If you see SERVFAIL, you are too late; the runway should have caught it days earlier.

How Netdata helps

Netdata’s BIND collector surfaces the signals that correlate with expire runway degradation:

  • Per-second query response code distribution shows SERVFAIL for a specific zone the moment it starts, before users report it.
  • Zone transfer counters from the BIND statistics channel show whether transfers are succeeding or failing in near real time.
  • Anomaly detection on query patterns flags the shift when a secondary starts refusing queries for an expired zone while other zones remain healthy.
  • Correlating transfer failures with network-level metrics (TCP connection state, primary reachability) shortens diagnosis from “zone expired, start investigating” to “transfers failed 3 days ago, here is why.”
  • Composite alerting across serial mismatch, transfer failure, and SERVFAIL matches the actual failure progression rather than a single binary alarm.