Hacker DirectoryHacker Directory

WEB / WEB-03.03

TTL, cache and delegation

Read a DNS answer’s time and authority scope, distinguishing fresh cache from stale fallback.

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mechanism

Read every scenario without motion

Fresh positive hit

  1. t=30: query ready

    The resolver entry is aged 30 seconds; this branch does not query parent/child authorities.

    Client stub
    Awaiting A answer
    Recursive resolver
    cache age=30; TTL=120
    Parent authority
    example.org authority
    Child authority
    lab.example.org authority
  2. Query arrived at resolver

    The notes.lab.example.org A query arrived; cache evaluation is a separate step.

    Client stub
    Awaiting A answer
    Recursive resolver
    query received; cache age=30
    Parent authority
    example.org authority
    Child authority
    lab.example.org authority
  3. Local fresh lookup

    30<120 leaves 90 seconds. This local clock calculation sends no packet to an authority.

    Client stub
    Awaiting A answer
    Recursive resolver
    fresh A=198.51.100.210; remaining=90
    Parent authority
    example.org authority
    Child authority
    lab.example.org authority
  4. Cached answer arrived

    The client received the A address with TTL=90; there was no new authoritative refresh.

    Client stub
    A=198.51.100.210; TTL=90
    Recursive resolver
    fresh A=198.51.100.210; remaining=90
    Parent authority
    example.org authority
    Child authority
    lab.example.org authority

Delegation after expiry

  1. t=120: equality boundary

    Fresh lifetime has ended; the selected model already knows parent context.

    Client stub
    Awaiting A answer
    Recursive resolver
    age=120; TTL=120
    Parent authority
    example.org ready
    Child authority
    lab.example.org ready
  2. Query received

    The resolver receives the new A query; with supplied entry age=120, cache evaluation remains the next local step.

    Client stub
    Awaiting A answer
    Recursive resolver
    query received; age=120
    Parent authority
    example.org ready
    Child authority
    lab.example.org ready
  3. Fresh miss

    120<120 is false. The resolver selects the parent authority locally.

    Client stub
    Awaiting A answer
    Recursive resolver
    fresh miss; parent selected
    Parent authority
    example.org ready
    Child authority
    lab.example.org ready
  4. Parent query arrival

    The parent received the notes.lab.example.org A query.

    Client stub
    Awaiting A answer
    Recursive resolver
    fresh miss; parent selected
    Parent authority
    query received; referral available
    Child authority
    lab.example.org ready
  5. Referral arrived at resolver

    NS target and required glue arrived; the final A answer is still absent.

    Client stub
    Awaiting A answer
    Recursive resolver
    referral ns1.lab.example.org; glue 192.0.2.54
    Parent authority
    query received; referral available
    Child authority
    lab.example.org ready
  6. Child selection is local

    192.0.2.54 was selected as the child authority endpoint.

    Client stub
    Awaiting A answer
    Recursive resolver
    child selected: 192.0.2.54
    Parent authority
    query received; referral available
    Child authority
    lab.example.org ready
  7. Child query arrival

    The resolver’s separate query arrived at the child; the parent did not forward it.

    Client stub
    Awaiting A answer
    Recursive resolver
    child selected: 192.0.2.54
    Parent authority
    query received; referral available
    Child authority
    query received; A=198.51.100.210
  8. Authoritative answer arrived

    The resolver received the child answer with TTL=120; local cache storage follows.

    Client stub
    Awaiting A answer
    Recursive resolver
    authoritative A received; TTL=120
    Parent authority
    query received; referral available
    Child authority
    query received; A=198.51.100.210
  9. New received entry

    The model stores a newly received entry aged 0; this event does not reset parent/glue timers.

    Client stub
    Awaiting A answer
    Recursive resolver
    fresh cache age=0; A=198.51.100.210
    Parent authority
    query received; referral available
    Child authority
    query received; A=198.51.100.210
  10. Client received answer

    The new A answer arrived with TTL=120; application connection is outside this scene.

    Client stub
    A=198.51.100.210; TTL=120
    Recursive resolver
    fresh cache age=0; A=198.51.100.210
    Parent authority
    query received; referral available
    Child authority
    query received; A=198.51.100.210

Type-scoped negative hit

  1. AAAA query, t=59

    The NODATA entry was received with TTL=60; existing A data is a different RRset.

    Client stub
    Awaiting AAAA answer
    Recursive resolver
    NODATA age=59; type=AAAA
    Parent authority
    no query in this branch
    Child authority
    no query in this branch
  2. AAAA query received

    The resolver received the v4only.lab.example.org AAAA query.

    Client stub
    Awaiting AAAA answer
    Recursive resolver
    AAAA query received; age=59
    Parent authority
    no query in this branch
    Child authority
    no query in this branch
  3. Type-scoped hit

    Name/type/class matches and remaining=1. This decision does not assert absence of A.

    Client stub
    Awaiting AAAA answer
    Recursive resolver
    NOERROR/NODATA; SOA remaining=1
    Parent authority
    no query in this branch
    Child authority
    no query in this branch
  4. NODATA answer arrived

    The client received AAAA NODATA; the A RRset remains present.

    Client stub
    AAAA NODATA; A still exists
    Recursive resolver
    NOERROR/NODATA; SOA remaining=1
    Parent authority
    no query in this branch
    Child authority
    no query in this branch

Permitted stale fallback

  1. Retained positive, t=150

    The retained entry is expired; serve-stale is enabled and child context is known.

    Client stub
    Awaiting A answer
    Recursive resolver
    retained age=150; original TTL=120
    Parent authority
    no parent query selected
    Child authority
    child endpoint known
  2. Query at resolver

    The client query arrived; no stale answer has yet been returned.

    Client stub
    Awaiting A answer
    Recursive resolver
    query received; retained expired entry
    Parent authority
    no parent query selected
    Child authority
    child endpoint known
  3. Refresh query at child

    The refresh query arrival is shown; no successful response is assumed.

    Client stub
    Awaiting A answer
    Recursive resolver
    query received; retained expired entry
    Parent authority
    no parent query selected
    Child authority
    refresh query received; outcome unavailable
  4. Local outcome: refresh unavailable

    The fixture selects failed refresh locally; this is neither a reply packet nor a measured timeout. Retention and policy permit fallback.

    Client stub
    Awaiting A answer
    Recursive resolver
    stale fallback selected; returned TTL=30
    Parent authority
    no parent query selected
    Child authority
    refresh query received; outcome unavailable
  5. Stale answer arrived

    The client received the old positive address with TTL=30. There is no new proof of authoritative freshness.

    Client stub
    A=198.51.100.210; stale fallback TTL=30
    Recursive resolver
    stale fallback selected; returned TTL=30
    Parent authority
    no parent query selected
    Child authority
    refresh query received; outcome unavailable

ACTORS · STATE · DATA FLOW

How long does an answer remain fresh?

TTL limits how long a recursive resolver treats a received RRset as fresh cache data. Our notes.lab.example.org A answer arrives at t=0 with TTL=120. Remaining lifetime is 90 at t=30, 1 at t=119 and 0 at t=120. At that equality boundary the ordinary fresh-cache branch is no longer eligible.

Time passing is not itself a DNS query packet. A query, prefetch or resolver policy may initiate refresh. Cache eviction can happen earlier; TTL does not promise retention. An authoritative zone record is not a recursive cache entry: supplying TTL=120 does not mean deleting the authoritative data after 120 seconds.

Negative answers are cached with distinct keys

In these simple cases NXDOMAIN says the queried name is absent, while NODATA says the name exists without an RRset of the requested type. With no aliases, missing.lab.example.org uses a name/class NXDOMAIN key; v4only.lab.example.org has A data and uses a name/type/class key for AAAA NODATA. Reusing AAAA absence as A absence breaks that scope.

If the SOA carried with an authoritative negative answer has TTL=300 and MINIMUM=60, its negative lifetime is min(300,60)=60. The cached SOA TTL counts down and this example stops reusing the negative entry at t=60. MINIMUM is not the current minimum TTL of every zone record. SERVFAIL or no response is not automatically NXDOMAIN.

Delegation hands a subtree to another authority

The example.org parent publishes ns1.lab.example.org as the NS target for lab.example.org. Beneath the zone cut the child has its own SOA and apex NS data. After the parent referral, the resolver sends a separate query to the child authority; the parent has not proxied the query to the child.

Because the NS target is inside the child, its initial address is needed: parent glue at 192.0.2.54 breaks that dependency. Glue is not an authoritative A answer for notes.lab.example.org. The artifact separates parent NS, glue address and the child answer at 198.51.100.210. A registrar handles registration and may also be a DNS operator, but is not a resolver hop in this query chain.

SOA timers govern a separate lifecycle

SOA REFRESH, RETRY and EXPIRE concern a secondary authoritative server maintaining its zone copy against a primary. The artifact selects REFRESH=3600, RETRY=600 and EXPIRE=86400; these are not product defaults. A successful SOA check with an equal SERIAL may require no transfer and restart the refresh schedule. It does not restart a recursive A entry’s TTL.

If no successful freshness check can be completed throughout EXPIRE, the secondary cannot keep serving its obsolete zone copy as authoritative data. Our selected model treats 86399 seconds since the last successful check as unexpired and 86400 as expired. A diagnosis saying “TTL expired” must identify the data, server role and timer involved.

Serve-stale is distinct from freshness

RFC 8767 permits policy-controlled use of retained expired data when authoritative refresh is unavailable. Our special branch has a positive entry aged 150 seconds with original TTL=120; refresh has failed and serve-stale is enabled. The resolver returns the old address with TTL=30. The entry remains stale; no new authoritative success is invented. Thirty seconds is recommended, not every resolver’s mandatory default.

Retention duration, freshness lifetime and the returned stale TTL are different measures. The RFC does not mandate one detailed algorithm; local policies and timers matter. An RR received with TTL=0 is transaction-only and must not become a retained stale entry. Our negative examples use ordinary expiry; negative serve-stale behavior is outside the animation.

Changes do not reach every cache simultaneously

Delegation NS, nameserver addresses, CNAME and terminal A/AAAA RRsets can have independent cache lifetimes. The artifact’s selected 600/300/120 seconds make that distinction visible. Publishing new zone data does not instantly reset the remaining lifetime of previously received fresh answers; resolvers received them at different times.

Rather than a single “DNS propagation takes five minutes” explanation, identify the changed RRset, parent/child scope and observed cache age. An inconsistent child NS address and parent glue, or a wrong alias chain, can disrupt resolution. Distinguishing fresh from stale and authoritative from cached data reveals where an old address came from.

2. Red · Trust & Impact

Read every scenario without motion

Stale boundary

  1. Availability and freshness were separated

    The positive entry arrived with a 120-second TTL and is not fresh at t=150. Returning a stale fallback does not show that authoritative refresh succeeded or that the address is still current.

    Resolver evidence
    Stale positive / t=150
    Classification gate
    No interpretation
    Application interpretation
    No application acceptance
  2. Necessary conditions were read together

    Fallback policy is enabled, the positive entry is retained and authoritative refresh failed. Those three conditions explain the stale reply. A returned TTL of 30 seconds does not reclassify the old entry as fresh.

    Resolver evidence
    Stale positive / t=150
    Classification gate
    Fallback policy / not fresh
    Application interpretation
    No application acceptance
  3. False certainty was not given to the application

    A fallback address can be returned, but assuming it remains the intended endpoint after a service move is unsupported. The application separately evaluates peer identity and resource policy.

    Resolver evidence
    Stale positive / t=150
    Classification gate
    Fallback policy / not fresh
    Application interpretation
    Freshness/identity separate
  4. Timers were not transferred between mechanisms

    Delegation NS has a 600-second lifetime, glue 300 and the answer 120. These belong to separate RRsets. One global propagation timer would lose their independent cache states.

    Resolver evidence
    NS 600 / glue 300 / answer 120
    Classification gate
    Fallback policy / not fresh
    Application interpretation
    Freshness/identity separate
  5. Secondary EXPIRE is a separate gate

    The last successful secondary check is at t=0 and EXPIRE is 86400 seconds. At equality this model stops using the zone. Recursive positive serve-stale policy does not automatically override that separate authority gate.

    Resolver evidence
    NS 600 / glue 300 / answer 120
    Classification gate
    Secondary EXPIRE ≠ cache TTL
    Application interpretation
    Freshness/identity separate
  6. The supported fallback boundary was preserved

    This branch classifies retained positive data as stale-fallback while fresh=false remains. Negative serve-stale behavior is outside this example. A record received with TTL=0 cannot be retained for later stale reuse. The returned answer proves neither new authoritative freshness nor service success.

    Resolver evidence
    NS 600 / glue 300 / answer 120
    Classification gate
    Secondary EXPIRE ≠ cache TTL
    Application interpretation
    Stale fallback; freshness unverified

Glue boundary

  1. Availability and freshness were separated

    Parent example.org. supplies NS target ns1.lab.example.org. and glue 192.0.2.54 for child lab.example.org. Glue is not the notes host’s final A answer.

    Resolver evidence
    Glue 192.0.2.54
    Classification gate
    No interpretation
    Application interpretation
    No application acceptance
  2. Necessary conditions were read together

    Glue has role=bootstrap-address-not-child-answer. Bootstrapping access to child authority is not a final resource-location decision.

    Resolver evidence
    Glue 192.0.2.54
    Classification gate
    Bootstrap ≠ child answer
    Application interpretation
    No application acceptance
  3. False certainty was not given to the application

    childAnswer for notes.lab.example.org. has address=198.51.100.210. Presenting glue .54 as the book endpoint loses the authority transition.

    Resolver evidence
    Glue 192.0.2.54
    Classification gate
    Bootstrap ≠ child answer
    Application interpretation
    Final A .210; not glue .54
  4. Timers were not transferred between mechanisms

    Delegation NS has a 600-second lifetime, glue 300 and the answer 120. These belong to separate RRsets. One global propagation timer would lose their independent cache states.

    Resolver evidence
    NS 600 / glue 300 / answer 120
    Classification gate
    Bootstrap ≠ child answer
    Application interpretation
    Final A .210; not glue .54
  5. Secondary EXPIRE is a separate gate

    The last successful secondary check is at t=0 and EXPIRE is 86400 seconds. At equality this model stops using the zone. Recursive positive serve-stale policy does not automatically override that separate authority gate.

    Resolver evidence
    NS 600 / glue 300 / answer 120
    Classification gate
    Secondary EXPIRE ≠ cache TTL
    Application interpretation
    Final A .210; not glue .54
  6. The supported fallback boundary was preserved

    Parent referral, glue bootstrap and child answer remain separate. The authority map proves neither DNSSEC nor an actual delegation change.

    Resolver evidence
    NS 600 / glue 300 / answer 120
    Classification gate
    Secondary EXPIRE ≠ cache TTL
    Application interpretation
    Glue bootstrap; child answer separate

ASSUMPTION · BOUNDARY · CONTROL

Broken assumption: absence applies to every type

An application interpreting AAAA NODATA as name-level NXDOMAIN may suppress valid A data too. The necessary condition is losing the negative result’s type scope; no special network operation is required. The impact is an incorrect fallback or rejecting legitimate access.

The control boundary is the negative cache key and result classification. Keeping the two key families separate makes clear what each answer does not establish.

Broken assumption: a referral is the final answer

Passing an NS target or glue address to the application as its requested host address erases the authority transition. The parent’s nameserver address is a way to reach child data, not proof of the notes server’s address. Parent/child disagreement may interrupt resolution.

The defensive task is to keep referral and answer data distinct and review consistency among parent NS, required glue and child authority during changes. This lesson does not perform delegation discovery on external targets.

Broken assumption: an answer proves successful refresh

Serve-stale can preserve availability without proving an address is current. It requires retained expired data, inability to refresh and a permitting policy. Losing that distinction can conceal use of an old endpoint after a service moves.

The control is recording freshness classification and refresh outcome. Assuming the same fallback for secondary-zone EXPIRE conflates mechanisms; this example is limited to recursive positive fallback.

3. Blue · Secure development & defense

Read every scenario without motion

TTL equality

  1. The clock meaning was established

    clock.kind=synthetic-relative-time and unit=seconds. receivedAt=0 begins this selected cache example, not a real wall clock or distributed ordering claim.

    Timer evidence
    Relative seconds / start 0
    Lifetime calculation
    No calculation
    Regression review
    No review
  2. The equality branch was calculated

    For a 120-second TTL, t=119 leaves one second and the entry is fresh. At t=120 the remaining lifetime is zero and the entry is not fresh. Remaining lifetime cannot become negative, but zero does not provide reusable freshness.

    Timer evidence
    Relative seconds / start 0
    Lifetime calculation
    TTL equality → not fresh
    Regression review
    No review
  3. A successful equal-SERIAL check is distinct

    The check at t=3600 finds the same SERIAL, 2026100801. No transfer is needed, but the check still succeeds. The last successful check advances to 3600 and the next refresh is scheduled at 7200.

    Timer evidence
    Equal serial / check successful
    Lifetime calculation
    TTL equality → not fresh
    Regression review
    No review
  4. Negative key scope was calculated

    NXDOMAIN is scoped by name and class; NODATA also includes requested type. Both selected TTL calculations give min(300, 60), or 60 seconds. The entry is fresh at t=59 and expired at t=60; type-specific absence is not expanded to the whole name.

    Timer evidence
    Equal serial / check successful
    Lifetime calculation
    NXDOMAIN vs NODATA / t=60
    Regression review
    No review
  5. A response did not replace refresh evidence

    Stale fallback is read with refreshAttemptOutcome=unable-to-authoritatively-refresh. Receiving a reply does not prove successful authoritative refresh; a missing outcome stays UNKNOWN.

    Timer evidence
    Equal serial / check successful
    Lifetime calculation
    NXDOMAIN vs NODATA / t=60
    Regression review
    Reply ≠ successful refresh
  6. Regression retained independent gates

    Positive/negative equality, successful secondary equal-SERIAL checks, expiry and glue/answer lifetimes are tested separately. Local arithmetic proves no real eviction, resolver or secondary-transfer behavior.

    Timer evidence
    Equal serial / check successful
    Lifetime calculation
    NXDOMAIN vs NODATA / t=60
    Regression review
    Timer scopes separate; runtime unmeasured

Secondary clock

  1. The clock meaning was established

    The secondary model starts with lastSuccessfulCheck=0 and measures expire=86400 seconds from that check. This is an authority lifecycle separate from a recursive cache receivedAt clock. Supplied times are not real wall-clock or synchronized-server observations.

    Timer evidence
    Secondary lastSuccessfulCheck=0
    Lifetime calculation
    No calculation
    Regression review
    No review
  2. The equality branch was calculated

    The secondary zone remains usable 86399 seconds after its last successful check. At the 86400-second EXPIRE boundary it becomes unusable in this model. The calculation uses the last successful check rather than record TTL.

    Timer evidence
    Secondary lastSuccessfulCheck=0
    Lifetime calculation
    EXPIRE equality → false
    Regression review
    No review
  3. A successful equal-SERIAL check is distinct

    In the separate equalSerialCheck example, the check at t=3600 receives the same SERIAL 2026100801. No transfer is needed, but the check succeeds: lastSuccessfulCheckAfter=3600 and nextRefreshAt=7200. The preceding expiry comparison used the initial state without this check; do not merge the two scenario clocks into one record.

    Timer evidence
    Equal serial / check successful
    Lifetime calculation
    EXPIRE equality → false
    Regression review
    No review
  4. Keep record-cache clocks separate

    Negative RRset caching uses 60 seconds from SOA TTL 300 and MINIMUM 60; that is not the secondary zone EXPIRE lifetime. NXDOMAIN stays name/class scoped and NODATA name/type/class scoped. This comparison does not change the secondary’s last successful check time.

    Timer evidence
    Equal serial / check successful
    Lifetime calculation
    Cache TTL 60 ≠ secondary EXPIRE 86400
    Regression review
    No review
  5. A response did not replace refresh evidence

    Stale fallback is read with refreshAttemptOutcome=unable-to-authoritatively-refresh. Receiving a reply does not prove successful authoritative refresh; a missing outcome stays UNKNOWN.

    Timer evidence
    Equal serial / check successful
    Lifetime calculation
    Cache TTL 60 ≠ secondary EXPIRE 86400
    Regression review
    Reply ≠ successful refresh
  6. Regression retained independent gates

    Positive/negative equality, successful secondary equal-SERIAL checks, expiry and glue/answer lifetimes are tested separately. Local arithmetic proves no real eviction, resolver or secondary-transfer behavior.

    Timer evidence
    Equal serial / check successful
    Lifetime calculation
    Cache TTL 60 ≠ secondary EXPIRE 86400
    Regression review
    Timer scopes separate; runtime unmeasured

IMPLEMENTATION · SECURITY CONTROL · VERIFICATION

Recompute the cache decision

Compute remaining=max(0,TTL−elapsed) from the artifact. At 119, 120 and 150 seconds, test elapsed<TTL before choosing a fresh branch. For a negative entry use min(SOA TTL,MINIMUM) and the correct key family.

This is a local reasoning exercise; the JSON is not sent to a resolver. Success means explaining time advancement, cache lookup and response arrival as separate events.

Keep separate evidence for authority and timers

A change record should separate RR owner/type, parent zone, child zone, NS target and required glue. Record whether the response came from cache or authority, its selected age and whether stale policy was used.

For a secondary, track successful SERIAL checks, last successful check time and EXPIRE computation. An equal SERIAL does not mean no check happened; a successful equal check can renew the freshness schedule.

Turn boundaries into regression cases

Positive TTL equality, negative TTL equality, type-specific NODATA, distinct parent/child data and permitted stale fallback are separate cases. Also check that a record received with TTL=0 cannot later be used as retained stale data.

The scene draws query and response arrivals. It does not execute secondary transfers, DNSSEC proofs, real timers or eviction algorithms. The inert example cannot establish actual product behavior in those areas.

NOW APPLY IT TO THE CASE

What do cache fallback, authority bootstrap and secondary lifetime prove separately?

The A record for notes.lab.example.org. has a 120-second cache lifetime. A stale fallback at t=150 does not make it fresh. Glue address 192.0.2.54 reaches the child authority rather than answering for the requested host.

Does a DNS answer establish the case’s correct book result? Separate the end of name-resolution knowledge from the start of HTTP and application observations.

Open the related case file ↗

READ THE EXAMPLE TOGETHER

Three clocks, two authorities: cache/delegation ledger

Select a field and examine what it supports and where the evidence ends.

Read the raw artifact and field explanations
{
  "clock": {
    "unit": "seconds",
    "receivedAt": 0,
    "kind": "synthetic-relative-time"
  },
  "positive": {
    "qname": "notes.lab.example.org.",
    "qtype": "A",
    "qclass": "IN",
    "address": "198.51.100.210",
    "receivedTtl": 120,
    "evaluations": [
      {
        "elapsed": 30,
        "remaining": 90,
        "fresh": true
      },
      {
        "elapsed": 119,
        "remaining": 1,
        "fresh": true
      },
      {
        "elapsed": 120,
        "remaining": 0,
        "fresh": false
      },
      {
        "elapsed": 150,
        "remaining": 0,
        "fresh": false
      }
    ]
  },
  "negative": [
    {
      "kind": "NXDOMAIN",
      "qname": "missing.lab.example.org.",
      "qclass": "IN",
      "cacheKeyFields": [
        "qname",
        "qclass"
      ],
      "soaTtl": 300,
      "soaMinimum": 60,
      "selectedTtl": 60
    },
    {
      "kind": "NODATA",
      "qname": "v4only.lab.example.org.",
      "qtype": "AAAA",
      "qclass": "IN",
      "cacheKeyFields": [
        "qname",
        "qtype",
        "qclass"
      ],
      "existingA": "198.51.100.211",
      "soaTtl": 300,
      "soaMinimum": 60,
      "selectedTtl": 60
    }
  ],
  "negativeEvaluations": [
    {
      "elapsed": 59,
      "remaining": 1,
      "fresh": true
    },
    {
      "elapsed": 60,
      "remaining": 0,
      "fresh": false
    }
  ],
  "delegation": {
    "parentZone": "example.org.",
    "childZone": "lab.example.org.",
    "parentNs": {
      "owner": "lab.example.org.",
      "target": "ns1.lab.example.org."
    },
    "glue": {
      "owner": "ns1.lab.example.org.",
      "address": "192.0.2.54",
      "role": "bootstrap-address-not-child-answer"
    },
    "childNs": {
      "owner": "lab.example.org.",
      "target": "ns1.lab.example.org."
    },
    "childAnswer": {
      "owner": "notes.lab.example.org.",
      "type": "A",
      "address": "198.51.100.210",
      "ttl": 120
    },
    "rootAndTld": "omitted-known-parent-context"
  },
  "secondary": {
    "refresh": 3600,
    "retry": 600,
    "expire": 86400,
    "lastSuccessfulCheck": 0,
    "serial": 2026100801,
    "evaluations": [
      {
        "elapsed": 86399,
        "zoneUsable": true
      },
      {
        "elapsed": 86400,
        "zoneUsable": false
      }
    ],
    "equalSerialCheck": {
      "at": 3600,
      "receivedSerial": 2026100801,
      "transferNeeded": false,
      "lastSuccessfulCheckAfter": 3600,
      "nextRefreshAt": 7200
    }
  },
  "serveStale": {
    "enabled": true,
    "retainedPositive": true,
    "elapsed": 150,
    "receivedTtl": 120,
    "refreshAttemptOutcome": "unable-to-authoritatively-refresh",
    "returnedTtl": 30,
    "fresh": false,
    "classification": "stale-fallback",
    "zeroTtlEligible": false,
    "negativeFallbackModeled": false
  },
  "independentLifetimes": {
    "delegationNsTtl": 600,
    "glueAddressTtl": 300,
    "answerTtl": 120,
    "meaning": "selected-independent-RRset-lifetimes-not-global-propagation-timer"
  }
}
positive.evaluations
Elapsed age, remaining lifetime and equality-boundary freshness for a received positive RRset.
negative.cacheKeyFields
NXDOMAIN name/class versus NODATA name/type/class scope.
delegation
Separate roles for parent referral, bootstrap glue and child answer.
secondary
Authoritative secondary-zone timers, separate from recursive TTL.
serveStale
Selected positive fallback only: fresh=false with returned TTL=30.

Times, SERIAL and addresses are original synthetic data. RRset summaries are not full DNS packets or a zone file. DNSSEC, real clocks, transfers, cache implementations and negative stale fallback are not executed.

Two reality checks

Expired TTL means old data can never be used.

Ordinary freshness ends; RFC 8767 allows stale use under refresh-failure and retention/policy conditions. TTL=0 data is not retained for that use.

SOA EXPIRE and a recursive answer’s TTL are the same timer.

EXPIRE bounds a secondary zone copy’s freshness; received RRset TTL governs recursive cache data. A successful equal SERIAL check can renew the former.

YOUR TURN

Work through this story.

Predict the outcome, find the evidence boundary, and explain it in your own words.

A positive entry has receivedTtl=120 and elapsed=120. Is it still fresh?

  1. No; remaining=0 and fresh=false.
  2. Yes; it expires only when elapsed>120.
Read the explained answer

No; remaining=0 and fresh=false. — The selected calculation has exhausted the TTL; equality does not grant another second of freshness.

Are the glue address and notes address the same information?

Selected lesson artifact fields; teaching example

delegation.glue
{"owner":"ns1.lab.example.org.","address":"192.0.2.54","role":"bootstrap-address-not-child-answer"}
delegation.childAnswer
{"owner":"notes.lab.example.org.","type":"A","address":"198.51.100.210","ttl":120}
  1. No; glue enables reaching the authority, while the child answer provides the notes resource.
  2. The glue address 192.0.2.54 is the final IP of the book resource.
Read the explained answer

No; glue enables reaching the authority, while the child answer provides the notes resource. — Glue gives 192.0.2.54 for ns1.lab; the notes A answer is 198.51.100.210.

The serve-stale branch returns a retained positive answer at elapsed=150. Why are TTL freshness and secondary SOA expiry not the same clock?

Read the explained answer

The 120-second entry is not fresh; selected refresh failure and enabled stale policy permit a bounded fallback. Secondary expiry instead determines zone usability since a successful authority check; it does not replace answer TTL. ReturnedTtl=30 does not prove the old entry is fresh.

□ I did not count a stale fallback as a fresh cache hit.

□ I distinguished SOA expiry from RRset TTL.

Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples

Sources and scope