Skip to main content

Command Palette

Search for a command to run...

DNS as a System (Part 5)

Updated
10 min readView as Markdown

Time to Live (TTL)

Time to Live (TTL)

Introduction

DNS was designed with one principle front and center: performance at scale. With billions of devices issuing DNS queries every day, querying authoritative nameservers for every single request would be catastrophic. The solution? Caching — and the mechanism that controls it is called Time to Live (TTL).

TTL is one of the most deceptively simple yet critically important concepts in DNS. Get it right, and your DNS infrastructure is fast, efficient, and resilient. Get it wrong, and you'll face either sluggish propagation of changes or an overloaded authoritative nameserver.

The Foundation: RFC 1034

Before diving into TTL mechanics, it's worth acknowledging where this concept comes from.

RFC 1034 — Domain Names: Concepts and Facilities
──────────────────────────────────────────────────────────────
Published:   November 1987
Section:     2.2 — Design Goals
Relevance:   Defines DNS caching and TTL as foundational principles

Key design goals from RFC 1034:
├─ The system must be capable of being queried frequently
├─ Locally cached data should reduce load on authoritative servers
├─ TTL controls the lifetime of cached data
└─ These principles have governed DNS for nearly 40 years

What are RFCs?
├─ RFC = Request for Comments
├─ Standard documents specifying internet protocols and best practices
├─ Published by the IETF (Internet Engineering Task Force)
└─ Reading RFCs is essential for deep understanding of any protocol

The Caching Analogy

The Detective's Notebook — Caching Analogy
──────────────────────────────────────────────────────────────
Scenario: A detective solves a case and records all clues in a notebook.

Without caching (no notebook):
└─ Every similar case → start from scratch
   → Re-interview witnesses, re-visit locations, re-gather evidence
   → Slow, expensive, repetitive

With caching (notebook):
└─ Similar case arises → check notebook first
   → If relevant notes exist → answer immediately
   → Only re-investigate when notes are outdated (TTL expired)

DNS equivalent:
├─ Notebook         = Resolver cache
├─ Case notes       = Cached DNS records
├─ Expiration date  = TTL value
└─ Re-investigating = Querying authoritative nameserver again

The Full DNS Resolution Chain

Understanding TTL requires understanding every component in the DNS resolution path — from your device to the authoritative nameserver.

Complete DNS Resolution Chain
──────────────────────────────────────────────────────────────

Step 1: Application
┌─────────────────────────────────┐
│  Your Application               │
│  (Browser, curl, ping, etc.)    │
│  Issues a DNS query             │
└─────────────────────────────────┘
           │
           ↓

Step 2: Stub Resolver (OS)
┌─────────────────────────────────┐
│  Stub Resolver                  │
│  (Built into the OS)            │
│  Linux: getaddrinfo() syscall   │
│  Checks OS-level DNS cache      │
│  Cannot query nameservers       │
│  directly — forwards upstream   │
└─────────────────────────────────┘
           │
           ↓

Step 3: Forwarding Resolver (Router)
┌─────────────────────────────────┐
│  Router / Forwarding Resolver   │
│  (Your home/office router)      │
│  First stop outside the device  │
│  May cache responses locally    │
│  Forwards to public resolver    │
└─────────────────────────────────┘
           │
           ↓

Step 4: Public Recursive Resolver
┌─────────────────────────────────┐
│  Recursive Resolver             │
│  (1.1.1.1, 8.8.8.8, ISP)       │
│  Performs full DNS tree walk    │
│  Maintains large shared cache   │
│  Caches per TTL values          │
└─────────────────────────────────┘
           │
           ↓

Step 5: Authoritative Nameservers
┌─────────────────────────────────┐
│  Root → TLD → Domain NS        │
│  Final authoritative answer     │
│  Only reached on cache miss     │
└─────────────────────────────────┘

Where Each Layer Caches

Caching at Every Layer
──────────────────────────────────────────────────────────────
Layer                   Cache Location              Scope
────────────────────────────────────────────────────────────────
Browser                 Internal DNS cache          Single app
Operating System        OS DNS cache (systemd-resolved, etc.)  All apps on device
Router                  Router firmware cache       All devices on network
ISP/Public Resolver     Resolver cache (1.1.1.1)   All users of that resolver

What Is TTL?

TTL (Time to Live) is a value attached to every DNS record that specifies — in seconds — how long a resolver is permitted to cache that record before it must re-fetch it from the authoritative nameserver.

TTL — Core Definition
──────────────────────────────────────────────────────────────
Field:       TTL (Time to Live)
Unit:        Seconds
Location:    Present in every DNS resource record
Purpose:     Controls how long cached data is considered valid
Analogy:     Expiration date on a carton of milk — after this date,
             discard and get fresh

When TTL expires:
├─ Cached record is marked stale and discarded
├─ Next query triggers a fresh lookup to authoritative nameserver
└─ New TTL value received and countdown restarts

Reading TTL With dig

The TTL value is visible in every dig response, right after the domain name.

bash

$ dig kodekloud.com
;; QUESTION SECTION:
;kodekloud.com.                 IN      A

;; ANSWER SECTION:
kodekloud.com.     300    IN    A    104.26.10.250
kodekloud.com.     300    IN    A    104.26.11.250
kodekloud.com.     300    IN    A    172.67.68.105

;; Query time: 166 msec
;; SERVER: 2806:10c0:ffff:e#53(2806:10c0:ffff::e)

TTL Field Breakdown

dig Answer Section — Field by Field
──────────────────────────────────────────────────────────────
kodekloud.com.   300   IN   A   104.26.10.250
      │           │     │   │         │
      │           │     │   │         └─ IP address (value)
      │           │     │   └─ Record type (A = IPv4)
      │           │     └─ Class (IN = Internet)
      │           └─ TTL: 300 seconds (5 minutes)
      └─ Domain name queried

Interpretation:
├─ This record will be cached for 300 seconds
├─ After 300 seconds, the resolver discards it
└─ Next query after expiry hits the authoritative nameserver

Watching TTL Count Down

# Query the same domain twice within the TTL window
# The second response's TTL will be lower — it's counting down

$ dig kodekloud.com | grep -A3 "ANSWER SECTION"
kodekloud.com.     300    IN    A    104.26.10.250   ← fresh cache

# Wait 60 seconds, query again
$ dig kodekloud.com | grep -A3 "ANSWER SECTION"
kodekloud.com.     240    IN    A    104.26.10.250   ← 60s consumed

# When TTL reaches 0 → resolver fetches fresh record

TTL Values: The Trade-Off

Setting the right TTL is a balancing act between freshness and performance.

High TTL — Pros and Cons

High TTL (e.g., 86400 seconds = 24 hours)
──────────────────────────────────────────────────────────────
Pros:
├─ Fewer queries to authoritative nameserver
├─ Faster responses (more cache hits)
├─ Lower infrastructure cost and load
└─ Better resilience (cached even if NS goes down briefly)

Cons:
├─ Slow propagation when records change
├─ Users may get outdated IP addresses for up to 24 hours
├─ DNS migrations (changing nameservers) take longer to propagate
└─ If you update an A record, old IP serves traffic until TTL expires

Low TTL — Pros and Cons

Low TTL (e.g., 60 seconds = 1 minute)
──────────────────────────────────────────────────────────────
Pros:
├─ Fast propagation of record changes
├─ Quick failover to new IPs
└─ Useful during planned migrations or deployments

Cons:
├─ More frequent queries to authoritative nameserver
├─ Higher server load and bandwidth usage
├─ Slower responses (more cache misses)
└─ Negates many benefits of caching infrastructure

TTL Comparison Table

TTL Value Duration Use Case
60s 1 minute Active migrations, frequent IP changes
300s 5 minutes Dynamic content, CDN, load-balanced IPs
3600s 1 hour Standard web services
86400s 24 hours Stable infrastructure, rarely changed records
604800s 7 days Highly stable records (MX, NS records)

The Pre-Migration Best Practice

TTL Strategy for DNS Migrations
──────────────────────────────────────────────────────────────
Problem: You want to change your A record IP with minimal downtime

Wrong approach:
├─ TTL = 86400 (24 hours)
├─ Change IP immediately
└─ Users stuck on old IP for up to 24 hours

Right approach:
├─ Step 1: Lower TTL to 300s well in advance (48–72 hours before)
│          → Allows existing 24h caches to expire
│          → New queries now cache for only 5 minutes
├─ Step 2: Make the IP change
└─ Step 3: New IP propagates globally within 5 minutes ✅
           Raise TTL back to 86400 after migration completes

TTL in Private Networks

DNS caching doesn't just happen at the resolver level — it also occurs within private networks at multiple independent layers, which can cause unexpected inconsistencies.

Multiple Cache Layers on a Single Device

Caching Layers Within a Single Device
──────────────────────────────────────────────────────────────
Application Layer:
├─ Web browsers (Chrome, Firefox) maintain their own DNS cache
├─ May apply their own TTL minimums (Chrome enforces min 1s)
└─ Flushing browser cache doesn't clear OS cache

Operating System Layer:
├─ Linux: systemd-resolved, nscd
├─ macOS: mDNSResponder
├─ Windows: DNS Client service
└─ Shared across all apps — but each app may override

Result:
├─ Same domain may resolve differently in browser vs. ping vs. curl
├─ One app sees new IP, another still uses old cached IP
└─ Can cause confusing, hard-to-diagnose issues

The Inconsistency Problem

Real-World Scenario — DNS Inconsistency
──────────────────────────────────────────────────────────────
You update your server's A record to a new IP.

Device behavior after update:
├─ ping kodekloud.com    → Uses OS cache → returns OLD IP
├─ curl kodekloud.com    → Uses OS cache → returns OLD IP
├─ Chrome browser        → Uses browser cache → returns OLD IP
└─ Firefox               → Browser cache expired → returns NEW IP

Why?
├─ Each application/layer cached the record at a different time
├─ Each has different cache expiry timing
└─ TTL countdown started at different moments for each

This is NOT a DNS problem — it's expected cache behavior.

Applications That Ignore TTL

TTL Non-Compliance in Applications
──────────────────────────────────────────────────────────────
Some applications override or ignore DNS TTLs:

Java applications:
└─ Historically cached DNS forever (networkaddress.cache.ttl = -1)
   → Required JVM restart to pick up DNS changes

Some older HTTP clients:
└─ Cache DNS for the lifetime of a connection pool
   → Ignores TTL entirely

CDN and proxy servers:
└─ May enforce minimum TTL regardless of record value
   → Cloudflare enforces minimum 30s TTL

Impact:
├─ DNS record changes propagate to most resolvers quickly
├─ But non-compliant apps may serve stale data for much longer
└─ Critical to know your application's DNS caching behavior

Clearing DNS Caches — Troubleshooting

When DNS issues arise, clearing caches at each layer is a key troubleshooting step.

Clearing OS-Level DNS Cache

# Linux (systemd-resolved)
$ sudo systemd-resolve --flush-caches

# Verify cache was cleared
$ sudo systemd-resolve --statistics | grep "Cache"

# Linux (nscd)
$ sudo service nscd restart

# macOS
$ sudo dscacheutil -flushcache
$ sudo killall -HUP mDNSResponder

# Windows
> ipconfig /flushdns

Clearing Browser DNS Cache

Browser DNS Cache Clearing
──────────────────────────────────────────────────────────────
Chrome:
└─ Navigate to: chrome://net-internals/#dns
   Click: "Clear host cache"

Firefox:
└─ about:config → network.dnsCacheExpiration → set to 0, then back to 60

Safari:
└─ Develop menu → Empty Caches (or Cmd+Option+E)

All browsers:
└─ Hard refresh: Ctrl+Shift+R (Windows) / Cmd+Shift+R (macOS)

DNS Troubleshooting Checklist

DNS Cache Troubleshooting Checklist
──────────────────────────────────────────────────────────────
Step 1: Check current TTL from authoritative source
└─ dig @8.8.8.8 yourdomain.com
   (bypasses local cache, queries Google's resolver)

Step 2: Check what your local resolver has cached
└─ dig yourdomain.com
   (uses default resolver — shows cached TTL countdown)

Step 3: Clear OS DNS cache
└─ sudo systemd-resolve --flush-caches  (Linux)
└─ ipconfig /flushdns                   (Windows)

Step 4: Clear browser DNS cache
└─ chrome://net-internals/#dns

Step 5: Test with different resolvers
└─ dig @1.1.1.1 yourdomain.com   (Cloudflare)
└─ dig @9.9.9.9 yourdomain.com   (Quad9)

Step 6: If still inconsistent — check application-level caching
└─ Does your app cache DNS independently?
└─ Restart the application or connection pool