FreeBSD nscd Operations: Cache Invalidation, TTLs, and NSS Staleness
Operate FreeBSD nscd with explicit cache scope, measured TTLs, negative-cache controls, and lookup tests that separate NSS from DNS.
Name-service failures often look like network failures because an application asks for a host or account name and receives an unexpected result. On FreeBSD, nsswitch.conf selects lookup sources for interfaces such as users, groups, hosts, services, and protocols. If nscd is running, cached results add another stateful layer between a process and those sources. A newly created account or updated host mapping can therefore coexist with a valid but stale cached answer.
This deep dive focuses on operating nscd, not changing lookup precedence or configuring a DNS server. Use getent and application-level checks to test the lookup path that matters. nscd is an NSS cache; it is not a replacement for authoritative DNS, and changing an nscd TTL does not change a DNS zone’s TTL.
Identify which cache and lookup path is involved
The FreeBSD manual describes nscd as a system caching daemon intended to work with the NSS subsystem. Common cache names include passwd, group, hosts, services, protocols, and rpc. The cache is per-user: ordinary cache entries belong to the user whose request populated them. This matters when an operator tests as root but the affected service runs under a different account.
Start with observations that do not mutate state:
service nscd status
sysrc nscd_enable
grep -v '^[[:space:]]*#' /etc/nsswitch.conf
getent hosts example.invalid
getent passwd serviceuser
Replace example names with a controlled test record and an actual account. The getent result shows NSS behavior for the invoking process; it does not prove that every application uses the same resolver API or cache context. If the failing application runs as a service account, reproduce the lookup as that account and capture its exact error. Also distinguish a failed NSS lookup from a DNS packet problem: a direct DNS query and an NSS request answer different questions.
The nscd.conf manual documents two cache styles, policies, TTLs, and an optional mode where nscd performs lookups itself. With the default caching behavior, it receives and caches NSS request results. perform-actual-lookups changes that boundary and is explicitly described as experimental in the manual; the documented supported cache names for that mode are passwd, group, and services. Do not enable it for hosts based on assumptions from another implementation or operating system.
Configure one cache deliberately
/etc/nscd.conf is read at daemon startup. The documented FreeBSD 15.1 Ports manual gives a default of eight worker threads, a positive TTL of 3600 seconds, a negative TTL of 60 seconds, and a positive cache-size limit of 2048 entries. Verify defaults on the target release and local configuration before relying on them. The negative confidence threshold defaults to one: one failed lookup is enough for a negative result to be cached.
For a frequently changing internal host mapping, a conservative example might be:
enable-cache hosts yes
positive-time-to-live hosts 120
negative-time-to-live hosts 5
positive-policy hosts lru
negative-policy hosts fifo
negative-confidence-threshold hosts 2
This is a policy illustration, not a universal recommendation. A short positive TTL can increase upstream lookup load; a long positive TTL can preserve a former address after a change. A short negative TTL reduces the time a newly created name can remain absent in the cache, but increases repeated lookup traffic for nonexistent names. A confidence threshold greater than one can cause nscd to retry a failed query against configured sources before retaining a negative result; it does not make a missing directory entry valid.
The cache’s positive and negative eviction policies are separate. FreeBSD documents FIFO, LRU, and LFU choices. Change a policy only after evidence shows that the current cache size or eviction behavior is a bottleneck. Increasing the hash table’s suggested-size is documented for cases where the number of cached elements is substantially larger than the default; arbitrary prime-number tuning without a measured cardinality problem is not operational rigor.
The configuration has a cache name as well as a value. Do not copy directives from a Linux configuration file without checking the FreeBSD manual: FreeBSD describes the syntax as mostly similar to Linux and Solaris but explicitly notes differences. Preserve an original copy, change one cache at a time, and keep the intended value in configuration management so a later package or host rebuild does not silently restore a different policy.
Invalidate at the right scope
The -i and -I options do not mean the same thing. nscd -i hosts asks the running daemon to invalidate the selected cache portion for the calling user’s cache. nscd -I hosts invalidates the selected cache for every user and is restricted to root. The manual permits all as a cache name to invalidate a user’s cache or, with the root-only form, the whole cache. The command contacts the already running daemon; it is not equivalent to restarting the service.
Use the narrowest invalidation that matches the incident:
# As the affected service account:
nscd -i hosts
# As root, when all users must observe the changed NSS data:
nscd -I hosts
The examples are runtime mutations. Capture the prior configuration and test evidence before invalidating if the stale answer is part of an incident record. The manual states that -i cannot be used for a cache whose perform-actual-lookups option is enabled. If a command fails, check whether the service is running, whether the selected cache is enabled, and whether the mode changes which administrative operation is allowed.
Restarting nscd is a broader action. It interrupts the daemon and discards its process state, so use it when the configuration changed or the process is unhealthy, not as the first response to every stale result. After a controlled restart, verify service status, inspect system logs, and repeat the same getent request as the affected user. A status of “running” does not prove that the daemon is answering the specific cache request correctly.
Diagnose stale positive and negative results separately
A stale positive result means a name resolved earlier but its data changed or its source became unavailable. Compare the result from NSS with the expected database entry, then inspect nsswitch.conf source order and the relevant source’s own state. For hosts, a local hosts-file entry, DNS source, or other NSS module may be responsible. Do not assume that editing a hosts file automatically flushes every process-specific or nscd cache.
A stale negative result is different: the lookup returned “not found,” and a negative cache entry may continue to mask a newly created record until expiration or invalidation. This is common during provisioning races where an application probes for an account or host before a configuration-management step creates it. Reduce the race by ordering dependencies and making the application retry with bounded backoff; cache policy is a secondary control, not a substitute for correct rollout ordering.
An nscd cache flush cannot repair an incorrect nsswitch.conf, an unreachable LDAP server, malformed local data, a missing DNS record, or a wrong service account. Test each boundary independently. On systems with multiple NSS sources, lookup order and action clauses can determine whether later sources are consulted. This article does not replace the source-order diagnostic workflow in the NSS guide.
Change configuration with a rollback path
Before editing /etc/nscd.conf, save the current file and record the exact target setting. Validate syntax against the installed nscd.conf(5) documentation; do not copy GNU/Linux directives merely because the names are similar. FreeBSD’s file format is described as mostly similar to Linux and Solaris, but the manual explicitly notes differences.
Use a maintenance window if the host provides authentication, name resolution, or directory lookups to other local services. Change one cache at a time, restart the daemon using the service framework, and test both a known-present and known-absent record. Record the TTL, result, invoking uid, and time. If behavior regresses, restore the saved file and restart again rather than layering undocumented overrides.
Example evidence collection:
date -u
service nscd status
getent hosts api.example.test
getent passwd buildsvc
nscd -I hosts
getent hosts api.example.test
Do not use an arbitrary .test name unless it exists in the environment. A negative lookup is useful only when its expected result is known. Keep cache invalidation commands out of unattended scripts unless the scope and privileges are explicit; root’s -I can affect every local user.
For a config change, save the original with ownership and mode preserved, compare the exact diff, then restart during an approved window. Confirm the daemon remains enabled as intended, verify logs for parse or startup errors, and query both one positive and one negative test name. A rollback is not just copying the old file back: repeat the daemon status and lookup checks after restoring it. Preserve command output with timestamps so operators can tell whether a change altered cache behavior or merely coincided with an upstream recovery.
Acceptance criteria
Close a stale-name incident only after the source data and nsswitch.conf path have been checked, cache scope is understood, the narrowest invalidation or measured TTL adjustment is applied, and the affected request succeeds as the real service identity. For configuration changes, verify daemon startup, test positive and negative cases, and document rollback. State separately whether NSS behavior was verified, whether DNS itself was queried, and which application was retested.
Caching makes repeated name lookups cheaper by retaining answers. It also makes cache ownership, freshness, and negative-result behavior part of operations. Treat those settings as an explicit consistency policy rather than a generic performance switch.
Related:
- FreeBSD NSS Operations: Trace getent Lookup Order Before Blaming DNS
- FreeBSD local-unbound Operations: Resolver Setup and DNSSEC Checks
Sources: