A TTL strategy that actually works

In this article · 15 sections
- Start with the right mental model
- What changing a TTL can and cannot do
- Positive caching is a freshness budget
- Negative caching makes absence sticky
- Resolver behavior is not uniform
- Provider controls are part of the design
- Multi-record answers need an RRset plan
- Serve-stale changes the failure mode
- DNSSEC adds validity clocks
- A staged migration playbook
- Worked example: moving an API name
- Test the path, not just the zone file
- A decision framework for choosing TTLs
- Conclusion
- References and further reading
DNS changes are often described as if a switch exists: lower the TTL, wait for propagation, then flip traffic. That model is convenient and frequently wrong. A DNS time to live is primarily an instruction to caching resolvers about the maximum age of an answer. It is not a universal failover timer, a command to every client to refresh, or a guarantee that an old answer disappears on schedule.
A workable TTL strategy starts with that narrower promise. It then accounts for negative answers, resolver policy, provider limits, DNSSEC, stale serving, the shape of the record set, health-check timing, and the applications that consume the result. The objective is not to find one perfect number. It is to make the freshness, availability, and operational cost of each DNS name deliberate.
Open the full-size diagramStart with the right mental model
DNS has authoritative servers and caching resolvers. The authoritative service publishes a zone; a recursive resolver asks the DNS hierarchy for an answer and stores what it learns. A stub resolver or application normally asks its configured recursive resolver rather than the authoritative server directly. A TTL is carried on each resource record and is measured in seconds.
RFC 1034, one of the two November 1987 DNS specifications, describes TTL as the time a resource record may be kept in a cache before it should be discarded. It also says the value is assigned by the administrator of the zone where the data originates. RFC 1035, published the same month, describes the TTL as the interval before the source should again be consulted and says zero means the record should not be cached. Those definitions describe cache freshness, not traffic-control semantics (RFC 1034; RFC 1035).
A resolver also decides when to refresh and which authoritative server to ask. An authoritative answer can be current while a recursive answer remains old, and a recursive answer can be current while an application continues using an earlier result held in its own process. This layered behavior is why a DNS dashboard showing the new value is necessary but not sufficient evidence of end-user freshness.
The practical path is therefore: publish a record, wait for authoritative service to serve it, let a resolver obtain it, and let that resolver reuse it until its remaining TTL reaches zero. Different users can be at different points in that path. One resolver may have a new answer while another still has the old one. A local operating-system cache, browser, library, forwarder, or service mesh can add another layer.
What changing a TTL can and cannot do
When a resolver receives an answer with a 3,600-second TTL, it normally counts that answer down locally. If the zone administrator changes the authoritative TTL to 60 seconds ten minutes later, the resolver does not receive a message about that edit. It already has the old answer and may use it for the balance of the original 3,600 seconds. Lowering a TTL changes answers fetched after the change; it does not invalidate an answer cached under the old TTL.
This is the most important migration rule: lower first, wait for the old maximum caching window, then change the value or destination. RFC 1034 explicitly suggests reducing a TTL before an anticipated change and raising it afterward. Google Cloud DNS describes the same two-step propagation model: the authoritative update must reach its servers, and resolvers must pick up the change when their cached records expire. Its guidance also warns that some resolvers ignore or alter the supplied TTL (Google Cloud DNS overview).
The same principle applies to NS and delegation changes, CNAME chains, and records used to find mail or service endpoints. A change to one name can be masked by a cached name higher or lower in the chain. Plan the relevant chain, not only the record you edit.
Positive caching is a freshness budget
A positive answer is an answer containing data, such as an A, AAAA, CNAME, MX, or TXT record. Its TTL trades authoritative-query load and change agility against cache-hit rate and resilience. A longer TTL can reduce repeated lookups and may improve lookup latency. A shorter TTL makes ordinary changes visible sooner, but increases query volume and makes a temporary authoritative outage more visible to resolvers that need to refresh.
There is no standards-defined universally correct value. RFC 2181, published in July 1997, calls TTL a maximum, not a mandatory lifetime, and says implementations may impose an upper bound. The same RFC requires all records in a resource-record set, or RRset, to have the same TTL; an RRset is the collection of records with the same owner name, class, and type (RFC 2181). Treat a configured TTL as an input to a distributed system, not a stopwatch that every participant must obey identically.
A useful policy also states what the TTL is protecting. Is the concern query cost, propagation speed, withdrawal risk, or tolerance for an authoritative outage? Those goals can conflict. For example, reducing a TTL may make a planned move easier but expose the system to more refreshes during a nameserver incident. If the business needs both fast withdrawal and outage tolerance, pair DNS with routing, access-control, or endpoint controls instead of forcing one TTL to satisfy incompatible goals.
Record the rationale, owner, normal TTL, emergency TTL, and the maximum old TTL encountered. This turns a number from folklore into a reviewable policy. Revisit it after observing resolver query rates and real change windows rather than automatically adopting another operator’s recommendation.
Negative caching makes absence sticky
Negative caching stores the result that a name or record type is absent. NXDOMAIN means the queried name does not exist. NODATA means the name exists for the class but has no record of the requested type. Both matter during launches, migrations, deletions, and typo recovery.
RFC 2308, a March 1998 Standards Track specification, defines how authoritative servers attach a negative-caching lifetime. For NXDOMAIN or NODATA, the authority section includes the zone’s SOA record. The negative TTL is the lesser of the SOA record’s TTL and the SOA MINIMUM field, and the resolver decrements it just as it does a positive TTL. When it reaches zero, the negative answer must not be used again (RFC 2308). The document also distinguishes the cache keys: NXDOMAIN is associated with name and class, while NODATA is associated with name, type, and class.
That means creating api.example after clients or resolvers previously asked for it can still look broken. They may be replaying a cached NXDOMAIN. Lowering the TTL of the future A record cannot clear a negative answer that was cached when the name did not exist. Before introducing a new name, publish it correctly and test from relevant recursive resolvers; do not generate widespread negative cache entries by testing a name before it exists unless you accept that consequence.
A deletion can have the reverse problem: a negative result may be cached longer than the operator expects, while a positive answer may remain elsewhere. For a rename, overlap old and new names at the application layer where possible, preserve the old endpoint for a documented period, and plan for both positive and negative caches.
Resolver behavior is not uniform
The authoritative TTL is not the only timing input. A recursive resolver may cap very high values, apply a local minimum, prefetch popular records, coalesce simultaneous misses, or retain data for a stale-serving feature. A corporate forwarder can add another cache between a user and a public resolver. Stub libraries and language runtimes can apply their own positive or negative caching rules.
This is why “DNS propagation completed in five minutes” is an unsafe statement. It may be true for a fresh query through one resolver and false for a user behind a forwarder with an older answer. Google Cloud DNS explicitly notes that some resolvers ignore the supplied TTL and that popular stub and recursive resolvers commonly cache negative responses for up to 15 minutes. That is operator guidance, not a universal limit; the relevant implementation and policy still need checking (Google Cloud DNS overview).
Provider controls are part of the design
Managed DNS products expose policy, but each product has its own constraints. Read the provider’s current documentation for the exact record type, routing mode, proxy status, minimum, maximum, and health-check behavior. Do not infer that a value accepted for an unproxied A record is accepted for an alias, NS record, or proxied hostname.
For example, AWS Route 53’s failover-record documentation says the TTL is how long recursive resolvers cache the record, notes the cost and lookup trade-off of longer values, recommends setting a shorter value before changing an in-use name, and recommends 60 seconds or less when the record is associated with a health check. It also says health checks are useful only in particular record-group configurations and that Route 53 checks the endpoint named by the health check, not automatically the IP in the record (Values specific for failover records). The 60-second value is AWS guidance for that feature, not a universal DNS standard.
Cloudflare documents a different constraint: proxied records use an Auto TTL of 300 seconds that cannot be edited, while DNS-only records have plan-dependent minimums and a one-day maximum on the referenced page. It also cautions that a local cache may make an actual change take longer than five minutes (Cloudflare Time to Live). This is a concrete example of why an architecture diagram should label whether a name is proxied.
Multi-record answers need an RRset plan
A DNS name may return multiple A or AAAA records. RFC 2181 treats records with the same name, class, and type as one RRset and requires a common TTL. That is a data and caching unit, not necessarily a load-balancing contract. A resolver can cache the set, return it in an order that changes, rotate it, or expose only part of it to a client; client selection and connection retry behavior vary.
If one address is removed, users may still receive the old RRset until the cached set expires. If the application retries another address, that can reduce impact; if it uses only the first address and never retries, DNS-level distribution will not provide reliable failover. A short TTL does not fix an application that resolves once and holds the result indefinitely.
Health-aware DNS adds two clocks: the provider’s detection and decision interval, and the resolver’s cache lifetime. A rough planning bound can include health-check detection, provider publication, authoritative distribution, and the remaining old TTL. It is not a guarantee because resolver behavior, query timing, network loss, and client retries vary. When availability is critical, combine DNS with endpoint redundancy, connection timeouts, retries, and an explicit traffic-management design.
Serve-stale changes the failure mode
Some recursive resolvers can serve an expired answer when they cannot refresh it. RFC 8767, published in April 2020, defines serve-stale behavior to improve resiliency when authoritative nameservers cannot be reached. It updates the TTL model so data can be retained beyond expiry in this specific failure context, and recommends that a stale response carry a positive TTL rather than zero in order to avoid client query storms (RFC 8767).
Serve-stale is not permission for an authoritative operator to assume that old data will always be used, nor is it a failover mechanism under the zone owner’s control. A resolver first attempts to refresh, then may use expired data after its local timers. The stale period, response timer, failure recheck timer, popularity rules, and cache pressure are implementation decisions. A stale answer can preserve reachability during an authoritative outage, but it can also direct users to a retired address after a deliberate change.
Unbound’s official documentation makes the distinction operational. Its older serve-expired mode can return expired data immediately and resolve in the background; its RFC 8767 mode uses expired data as a fallback after normal resolution has had time to fail. The documentation warns that serving expired data may direct clients to places long gone and says administrators should consult the version-specific configuration manual (Unbound Serving Stale Data).
DNSSEC adds validity clocks
DNSSEC authenticates DNS data with digital signatures. It does not make cached data refresh instantly. A validating resolver still caches RRsets according to TTL, and it also evaluates the signature’s validity interval and the chain of trust. A record can be within its ordinary TTL yet fail validation if signatures, keys, or their timing are mismanaged.
RFC 4034, the March 2005 DNSSEC resource-record specification, says an RRSIG’s TTL must match the TTL of the RRset it covers and includes an Original TTL field because a caching resolver decrements the cached TTL while validation needs the authoritative original value. It also defines signature inception and expiration times (RFC 4034). In practice, changing a signed record means considering the signer’s publication process, RRSIG refresh schedule, DNSKEY or DS changes, and resolver validation behavior—not simply editing an A record.
For planned migrations, verify that the new RRset and signatures are visible from authoritative servers before lowering or changing traffic records. Keep old keys and records through the provider’s documented rollover procedure. The exact safe intervals depend on the signer and resolver populations, so treat DNSSEC maintenance as a separate change plan that happens to share the same cache-freshness constraints.
A staged migration playbook
Begin with an inventory. For each name, record its type, alias or CNAME chain, authoritative provider, proxy status, served TTL, negative SOA policy, DNSSEC status, health-check policy, application resolution behavior, and target shutdown risk. Identify the highest TTL that may already be cached, including delegation and intermediate records. Define what must be true before the old target can be disabled.
Make the destination safe before making it visible: provision it, install certificates, test authentication and writes, and make the application tolerate overlap. For mail, keep old and new MX destinations able to accept mail during the overlap; DNS timing alone is not a mail-delivery guarantee. For APIs, use compatibility and rollback controls so a mixed population of old and new answers is acceptable.
Then lower the TTL of the records that will change, using a value your provider permits and your authoritative service can sustain. Do it sufficiently before the cutover to age out answers served with the old value. The necessary lead time is a property of observed and configured caches, not a universal 24- or 48-hour rule. Verify the authoritative response and sample recursors during the waiting period.
Set an explicit abort condition before the window: for example, a rise in connection failures, a validation error, or a target that receives traffic without passing readiness checks. Give one person authority to pause and another authority to validate. This is operational discipline rather than a DNS rule, but it prevents a misleadingly low TTL from turning a reversible change into a rushed outage response.
At the change window, publish the new answer or routing policy, confirm the zone serial or provider change state, and query authoritative servers and several recursive resolvers. Watch application success rates, connection errors, endpoint traffic, DNS response codes, and resolver query volume. Keep the old target available until the longest planned cache, stale, application, and rollback window has passed. Roll back by restoring a known-good answer, but remember that rollback is also subject to caching.
After stability is demonstrated, raise the TTL only if the resulting freshness budget is acceptable. Record the actual timeline, anomalies, and observed resolver behavior. A migration runbook should explicitly state that lowering a TTL after a bad answer was cached cannot recall that answer.
Worked example: moving an API name
Suppose api.example currently serves one A RRset with a 7,200-second TTL. The target will move from blue to green, and the application can tolerate both during a short overlap. At 09:00 on Monday, an operator changes the authoritative TTL to 300 seconds. That change is useful for resolvers that refresh after 09:00, but it does not affect a resolver that fetched the 7,200-second answer at 08:59. The conservative old-answer horizon is therefore about 7,200 seconds after that fetch, not five minutes after the edit.
At cutover, publish green while blue remains available. Monitor both target traffic and errors. If a resolver still returns blue, that is expected within its old cache budget; if a client has a persistent local cache or connection pool, its behavior may last longer. Once the mixed-answer period is safely over, decommission blue only after checking the application and any stale-serving policy. Finally, choose a steady-state TTL based on how often the name changes, query cost, outage tolerance, and rollback needs—not because 300 seconds is a magic value.
The example is intentionally illustrative. A service with dangerous endpoint withdrawal, a large global resolver population, or a provider-enforced minimum needs a different sequence and perhaps an application or traffic-management control beyond DNS.
Test the path, not just the zone file
A useful test has four layers. First, query each authoritative nameserver directly and compare the RRset, TTL, SOA serial, DNSSEC records, and response code. This answers whether the source is consistent. Second, query several recursive resolvers from more than one network and record answer order, remaining TTL, CNAME hops, and authority-section negative evidence. Third, inspect the local stub, operating-system cache, language runtime, and service discovery agent. Fourth, exercise the application: resolution, connection establishment, retries, long-lived sessions, and behavior when one returned address fails.
Use commands such as dig @ns1.example.net api.example A +noall +answer +authority, dig @resolver.example api.example A +noall +answer +authority, and dig +trace api.example where trace behavior is appropriate. Do not treat +trace as a measurement of what an end user sees; it bypasses the normal recursive cache path. Repeat queries over time to observe countdown and refresh rather than relying on one snapshot.
A test should also verify the authority section, not only the answer section. For NXDOMAIN, confirm the SOA and its effective negative TTL; for NODATA, confirm that the name exists but the requested type does not. Compare the result with the provider’s configured SOA values. This catches a common mistake in which a positive-record change is blamed for a negative cache created by an earlier probe.
For negative tests, query an intentionally unused name only when you understand the cache consequence, then create it and measure recovery from multiple recursors. For failover, simulate the health-check condition and distinguish provider decision time from the time clients continue receiving cached data. For DNSSEC, test validation during ordinary service, key rollover, and the intended rollback path.
A decision framework for choosing TTLs
Separate freshness from failover. A record can have a short TTL and still fail to provide fast failover if clients do not re-resolve, health checks are slow, or the old answer is served stale. Conversely, a longer TTL can be acceptable when targets are interchangeable and the application retries. The decision should begin with the observed client behavior and risk, then choose a cache budget that supports it.
Ask first how harmful a stale answer is. If a stale target is merely an inconvenience, a longer TTL may buy efficiency and resilience. If it can expose a retired service, misroute writes, or prolong a security incident, choose a shorter normal window and add non-DNS controls for urgent withdrawal. If the answer must support availability during authoritative outages, evaluate resolver serve-stale behavior and keep old targets safe rather than assuming low TTL is protective.
Ask how often the name changes and how predictable those changes are. Stable names can usually carry a longer cache budget if rollback is planned. Frequently changing names may need shorter TTLs, but frequent DNS changes can be a symptom that the control belongs in a load balancer, service registry, or application-level routing layer. DNS is deliberately distributed and eventually fresh; it is rarely a precise per-request switch.
Ask what the provider and consumers actually do. Confirm minimums, maximums, proxy behavior, alias synthesis, health-check semantics, negative SOA settings, DNSSEC signing, and any documented resolver clamps. Confirm whether clients resolve per request, per process, per connection, or on a library-specific schedule. The right TTL for a browser-heavy public site may be wrong for an internal job runner or mail exchanger.
Finally, write the policy as a range of scenarios rather than a universal number: normal operation, planned migration, emergency rollback, endpoint withdrawal, authoritative outage, negative-cache recovery, and DNSSEC rollover. Each scenario should name the expected cache window, dependencies, measurements, and non-DNS safeguards. Review it after incidents and migrations. A TTL strategy works when the organization can predict what may remain cached, observe it, and keep every old answer safe for the time it may still be served.
Conclusion
TTL is a resolver-cache freshness contract with qualifications, not a universal failover timer. Positive answers age independently across caches; lowering a TTL cannot invalidate an answer already cached under the old TTL. NXDOMAIN and NODATA can be cached too. Providers, clients, DNSSEC, multi-record sets, health checks, and serve-stale policies add separate clocks and failure modes.
The practical discipline is straightforward: inventory the path, publish and test the destination first, lower TTL before the change, wait out the old cache, overlap safely, measure several resolver and application paths, and keep non-DNS controls for urgent failover or withdrawal. Choose values from the service’s risk and operating constraints, document the assumptions, and verify the behavior on the wire. That is how DNS becomes a predictable part of a migration and availability plan rather than a source of folklore.
References and further reading
- RFC 1034: Domain Names—Concepts and Facilities
- RFC 1035: Domain Names—Implementation and Specification
- RFC 2181: Clarifications to the DNS Specification
- RFC 2308: Negative Caching of DNS Queries (DNS NCACHE)
- RFC 4034: Resource Records for the DNS Security Extensions
- RFC 8767: Serving Stale Data to Improve DNS Resiliency
- Google Cloud DNS overview: Performance and timing
- Values specific for failover records
- Time to Live (TTL)
- Serving Stale Data

Operating DNS at the edge
A research-grounded guide to operating DNS with anycast: routing realities, node readiness, monitoring, capacity, deployment, and incident response.

Building DNS that survives bad days
What we learned designing DNS architecture that keeps resolving when providers, links and regions fail at the same time.

Edge computing without the buzzwords: placement, state, and operations
Decide where edge workloads belong by balancing latency, state, residency, disconnected operation, orchestration and operational risk.