During an incident, named can feel like a black box. A single process handles packet reception, DNS parsing, ACL evaluation, cache lookup, zone lookup, recursive fetch, DNSSEC validation, RPZ policy enforcement, and response serialization. There is no separate resolver process, no separate authoritative process, no separate cache daemon. Every query flows through the same pipeline, and every subsystem competes for the same pool of CPU, memory, file descriptors, and kernel network buffers.

What it is and why it matters

BIND (ISC BIND 9.x) serves as both a recursive resolver and an authoritative server, and can do both on the same instance. ISC explicitly recommends against mixed-role deployments.

The failure modes are not random. They follow from the architecture. When the cache subsystem and the zone database share the same process memory, the recursive fetch state table has a hard limit, and the network manager uses one worker thread per core, you can trace any symptom back to the component responsible.

The statistics channel exposes counters via JSON at /json/v1/* and XML at /xml/v3/*. Counter names are stable across BIND 9.16+. They are cumulative since process start, zero-valued counters are omitted by default, and there is no native end-to-end latency histogram. Knowing which counter maps to which pipeline stage is what separates effective monitoring from noise.

How it works

The query pipeline

Every DNS query that reaches named passes through a fixed sequence of stages:

flowchart LR
    A[Receive packet] --> B[Parse]
    B --> C{ACL / view}
    C -->|deny| R[REFUSED]
    C -->|allow| D{Recursive?}
    D -->|yes| E{Cache hit?}
    D -->|no| F[Zone DB]
    E -->|hit| P[RPZ + DNSSEC]
    E -->|miss| G[Fetch upstream
via recursive-clients slot] G --> P F --> P P --> S[Serialize + send]

The stages, with their operational significance:

Receive. UDP sockets handle the majority of traffic. TCP handles queries that exceed UDP size limits, zone transfers, and clients configured for TCP. The kernel’s UDP receive buffer sits between the wire and named. If that buffer overflows, packets are dropped before BIND sees them. There is no counter, no log entry, no signal in the statistics channel. The only evidence is RcvbufErrors in the Udp: line of /proc/net/snmp.

Parse. The incoming packet is decoded into an internal query structure. Malformed packets consume extra CPU here. OpCodes and QTypes are classified into the statistics counters at this stage.

ACL and view check. BIND evaluates match-clients, allow-query, allow-recursion, and view configuration. A denied query returns REFUSED. This is correct behavior, not an error. On public authoritative servers, background REFUSED from random Internet hosts probing for open recursion is expected noise.

Cache lookup (recursive path). If recursion is enabled for the matching view, BIND checks the in-memory cache. A hit returns the cached answer directly. A miss triggers a recursive fetch upstream.

Zone lookup (authoritative path). If the query targets a zone BIND is authoritative for, the answer comes from the in-memory zone database. This is a pure memory lookup, typically sub-millisecond.

Recursive fetch. On a cache miss, BIND sends a query upstream. Each in-flight recursive query holds a slot in the recursive-clients table. The default limit is 1000, with a soft quota at 90% (900). Beyond the soft quota, BIND starts rejecting new recursive queries. At the hard limit, new recursive queries receive SERVFAIL. Each slot is held for the duration of the upstream fetch, bounded by resolver-query-timeout (default 10 seconds). Slow or unresponsive upstream servers hold slots longer, which is the mechanism behind the most common recursive resolver outage pattern: upstream latency fills the table, and healthy queries get rejected as collateral damage.

Apply RPZ and DNSSEC. Response Policy Zone rules are evaluated, potentially rewriting the response. DNSSEC validation runs if enabled, adding cryptographic verification overhead. This is CPU-intensive, especially for RSA keys above 2048 bits.

Serialize and send. The response is encoded and written to the socket.

Internal machinery

Network manager (netmgr). Since BIND 9.18, the legacy socket manager is gone entirely. netmgr uses libuv for asynchronous I/O multiplexing with one worker thread per CPU core by default. The -n flag overrides the worker count. CPU saturation manifests as worker thread contention and softirq pressure, not as a clean queue depth metric.

Cache subsystem. For recursive resolvers, the in-memory cache is bounded by max-cache-size. The default is 90% of physical memory for views with recursion yes, and 2 MB for views with recursion no. Eviction under memory pressure discards entries by LRU, tracked via the DeleteLRU counter in cachestats. This reduces cache hit ratio, which increases outbound queries, which increases latency and resource consumption. The result is a self-reinforcing degradation loop. BIND does not release freed memory back to the OS efficiently due to allocator fragmentation. RSS climbs and stays.

Zone database. Authoritative zone data lives in memory. Journal files (.jnl) handle dynamic updates and IXFR. Zone transfers (AXFR for full, IXFR for incremental) use TCP on port 53. The SOA serial number drives the transfer protocol between primaries and secondaries.

Address Database (ADB). Tracks reachability and round-trip time to upstream authoritative servers for server selection during recursive resolution. BIND preferentially queries faster nameservers and applies an RTT band so that nameservers within a similar latency range are used interchangeably. The ADB can consume significant memory with many unique upstream targets.

DNSSEC engine. In recursive mode, validates every answer against the chain of trust using managed trust anchors via RFC 5011. In authoritative mode, signs zones with inline signing. DNSSEC validation requires accurate time. Clock drift outside RRSIG validity windows causes validation failures (SERVFAIL) for signed domains while unsigned domains continue to work.

Control plane. rndc commands flow via TCP port 953 (or a Unix socket). The statistics channel serves HTTP. These are separate from the data plane on port 53 and can degrade independently. If rndc status hangs while queries still work, the control plane is starved, which blocks incident response before the query path fails completely.

Where it shows up in production

The pipeline and machinery produce predictable failure archetypes when resources are constrained. These are not edge cases. They are the direct consequences of the architecture under load.

Failure patternPipeline stageWhat happens
Recursive client exhaustionRecursive fetchOutstanding fetches pile up, fill the table, new queries get SERVFAIL
Cache pressure spiralCache lookupUndersized cache drives low hit ratio, more upstream queries, more latency
Upstream dependency failureRecursive fetchForwarders slow or unreachable, slots consumed for full timeout duration
UDP packet dropsReceiveKernel buffer overflows, packets lost before BIND sees them
Zone staleness cascadeZone lookupTransfer failures leave secondaries serving stale data until SOA expire
DNSSEC time bombApply RPZ/DNSSECExpired signatures cause validating resolvers worldwide to reject the zone
Memory exhaustion to OOMAll stagesUnbounded cache or leak triggers OOM kill, cold restart storm follows

Each pattern traces to a specific stage and a specific contested resource. The recursive client exhaustion archetype is the direct consequence of the recursive fetch stage holding slots with a hard cap. The cache pressure spiral is the direct consequence of LRU eviction interacting with recursive fetch slot demand.

Why mixed-role servers mask failure signals

ISC explicitly recommends against combining authoritative and recursive functions on the same server set. The recursive workload is variable and unpredictable, and consumes resources needed for authoritative service.

The monitoring problem is structural. When a single BIND instance serves both roles, aggregate statistics conflate two fundamentally different signal profiles. A cache miss spike on the recursive side elevates RecursClients and outbound query rate, but those counters are irrelevant to the authoritative path. An authoritative zone failing to load produces SERVFAIL for that zone, but on a mixed-role server, that signal is buried under recursive traffic noise.

Teams running mixed-role BIND monitor aggregate statistics and miss zone-specific authoritative failures. Per-view monitoring is essential if both roles must share one instance. Better to separate them into different server sets so the failure domains do not overlap.

This masking effect extends to other deployment variants. Anycast deployments can hide per-node saturation behind stable global aggregates. Split-horizon setups produce failures that look different depending on the source IP, which aggregate stats never catch. Hidden primaries never receive direct queries, so query-volume monitoring is useless for them. Transfer health and zone serial consistency are the only signals that matter for secondaries and hidden primaries.

Signals to watch in production

SignalWhy it mattersWarning sign
RecursClients (gauge, not counter)Approaching the recursive-clients limit means imminent cliff-edge SERVFAILSustained above 50% of limit; soft quota at 90%
QrySERVFAIL ratioSERVFAIL means BIND failed to complete the work. Server can appear up while returning 100% SERVFAILAbove 0.1% of classified responses
Cache hit ratio (CacheHits / (CacheHits + CacheMisses))Low hit ratio drives more upstream queries, compounding loadDrop below baseline after warmup period
RcvbufErrors (/proc/net/snmp, UDP line)Packets dropped by kernel before BIND sees them. Invisible to all BIND countersAny sustained non-zero rate
SOA serial consistencySecondary serving stale data, approaching expiry cliffSerial mismatch persisting beyond refresh interval
ValFail (per-view resolver stat)DNSSEC validation failures produce SERVFAIL for signed domainsAny sustained increase from near-zero baseline
Process RSSMemory growth toward OOM killSteady climb after warmup plateau

How Netdata helps

Netdata’s BIND collector pulls from the statistics channel and the OS level, correlating signals that are normally scattered across different tools:

  • Per-second resolution on RecursClients as a percentage of the configured limit, so the soft-quota threshold and the hard cliff are visible as a trend, not just a point-in-time snapshot.
  • QrySERVFAIL rate computed automatically from cumulative counters, so the ratio is visible without manual delta math against raw counters.
  • Cache hit ratio derived from per-view CacheHits and CacheMisses, correlated with RecursClients and upstream RTT buckets in the same dashboard.
  • Kernel UDP receive errors from /proc/net/snmp, collected at the OS level and overlaid against BIND query rate, closing the most common monitoring blind spot.
  • ML-based anomaly detection on response code distribution and query rate patterns, surfacing gradual degradation that binary health checks miss.