DNS is the first thing that breaks and the last thing you check. Understanding it properly saves hours of debugging “it works on my machine.”

Record Types You’ll Actually Use

A and AAAA

Point domain to IP address:

eexxaammppllee..ccoomm..AAAAA9236.0168:42.820106:.23240:1:248:1893:25c8:1946

CNAME

Alias to another domain:

wawpwi..eexxaammppllee..ccoomm..CCNNAAMMEEeaxpaim-pllbe-.1c2o3m..us-east-1.elb.amazonaws.com.

Cannot be used at zone apex (root domain). Use ALIAS/ANAME instead.

ALIAS / ANAME (Provider-specific)

CNAME-like behavior at zone apex:

#e#exxRaCaomlmupoptluleede.f.5clc3oaomrmA.e.liCaNsAMAECLNIfAAlMSaEttedne1ix2na3gm.pclleo.undeftrloinfty..naeptp..(flattenedtoA)

MX

Mail servers:

eexxaammppllee..ccoomm..MMXX1200mmaaiill12..eexxaammppllee..ccoomm..

Lower priority number = preferred.

TXT

Verification and policies:

#e#s#e_xexaSaDlDacPmKeommFpIcmpelMtal-(eoiece.rn.hmc.caao_volimdemll.or.eminaafguiietnc.hkaeeTetTxnXyiXatT.oTmienpcxlaaet"m".ivpgco=loonseom)p.g.fcl1oem-i.sTniXctTleuT-dXveTe":rL_iEsfTp"i_fvcE.=aNgDtCoKiRoIoYgMnPl1=Te;a_.bVckcAo=1Lmr2Is3D~a"Aa;TlIlpO"=NM_ITGOfK.E.N.""

SRV

Service discovery:

_#htPtrpi.o_rtictpy.eWxeaimgphlte.Pcoormt.TargSeRtV10580www.example.com.

Used by some protocols (SIP, XMPP, Minecraft).

CAA

Certificate Authority Authorization:

eeexxxaaammmpppllleee...cccooommm...CCCAAAAAA000iiissossduueeefw"i"llmedatis"leltneoct:rssyeepnctcu.rroyirptgty".@oerxga"mple.com"

Only listed CAs can issue certificates for your domain.

TTL Strategy

Time To Live determines caching duration:

#e#a#oxplLaSiVdomh.e.npoereglrxyxetaaT.msmTcTphpLoTlolmLere(..t.1(cc5oTodmTmam.L.yi)n()1--msit8r3n6a6e0)0b4c0l0o-e0rddrsuercAyCiCooNnNruAgAdMMsmEmEiigg9harn3tpae.itw1c-i.8hloe4abnx.n.a2gam1ewp6sl..e3c.4ocmo.m.

TTL Best Practices

Before a migration:

  1. Lower TTL to 5 minutes (24-48 hours ahead)
  2. Wait for old TTL to expire
  3. Make the change
  4. Verify propagation
  5. Raise TTL back to normal
1
2
3
4
5
# Check current TTL
dig example.com +noall +answer

# Monitor propagation
watch -n 30 "dig @8.8.8.8 example.com +short"

Route 53 Patterns

Simple Routing

Basic DNS without health checks:

1
2
3
4
5
6
7
resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "www.example.com"
  type    = "A"
  ttl     = 300
  records = ["93.184.216.34"]
}

Weighted Routing

Distribute traffic by percentage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
resource "aws_route53_record" "api_blue" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "blue"
  
  weighted_routing_policy {
    weight = 90
  }
  
  alias {
    name    = aws_lb.blue.dns_name
    zone_id = aws_lb.blue.zone_id
  }
}

resource "aws_route53_record" "api_green" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "green"
  
  weighted_routing_policy {
    weight = 10  # Canary: 10% of traffic
  }
  
  alias {
    name    = aws_lb.green.dns_name
    zone_id = aws_lb.green.zone_id
  }
}

Failover Routing

Automatic failover with health checks:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
resource "aws_route53_health_check" "primary" {
  fqdn              = "primary.example.com"
  port              = 443
  type              = "HTTPS"
  resource_path     = "/health"
  failure_threshold = 3
  request_interval  = 30
}

resource "aws_route53_record" "api_primary" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "primary"
  
  failover_routing_policy {
    type = "PRIMARY"
  }
  
  health_check_id = aws_route53_health_check.primary.id
  
  alias {
    name    = aws_lb.primary.dns_name
    zone_id = aws_lb.primary.zone_id
  }
}

resource "aws_route53_record" "api_secondary" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "secondary"
  
  failover_routing_policy {
    type = "SECONDARY"
  }
  
  alias {
    name    = aws_lb.secondary.dns_name
    zone_id = aws_lb.secondary.zone_id
  }
}

Latency-Based Routing

Route to nearest region:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
resource "aws_route53_record" "api_us" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "us-east-1"
  
  latency_routing_policy {
    region = "us-east-1"
  }
  
  alias {
    name    = aws_lb.us_east.dns_name
    zone_id = aws_lb.us_east.zone_id
  }
}

resource "aws_route53_record" "api_eu" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "api.example.com"
  type           = "A"
  set_identifier = "eu-west-1"
  
  latency_routing_policy {
    region = "eu-west-1"
  }
  
  alias {
    name    = aws_lb.eu_west.dns_name
    zone_id = aws_lb.eu_west.zone_id
  }
}

Internal DNS

Private Hosted Zones

DNS for internal services:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
resource "aws_route53_zone" "internal" {
  name = "internal.example.com"
  
  vpc {
    vpc_id = aws_vpc.main.id
  }
}

resource "aws_route53_record" "database" {
  zone_id = aws_route53_zone.internal.zone_id
  name    = "db.internal.example.com"
  type    = "A"
  ttl     = 60
  records = [aws_db_instance.main.address]
}

Service Discovery

Kubernetes internal DNS:

#ccuuPrrolldhhcttattnpp::r/e/aaacpphii--ssseeerrrvvviiiccceees.dbe#yfaSnuaalmmtee.snvacm.ecslpuascteers.hloorctahland

AWS Cloud Map for ECS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
resource "aws_service_discovery_private_dns_namespace" "internal" {
  name = "internal.local"
  vpc  = aws_vpc.main.id
}

resource "aws_service_discovery_service" "api" {
  name = "api"
  
  dns_config {
    namespace_id = aws_service_discovery_private_dns_namespace.internal.id
    
    dns_records {
      ttl  = 10
      type = "A"
    }
  }
}

Debugging DNS

dig

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Basic lookup
dig example.com

# Specific record type
dig example.com MX

# Use specific DNS server
dig @8.8.8.8 example.com

# Trace resolution path
dig +trace example.com

# Short output
dig example.com +short

Common Issues

Negative caching:

1
2
3
4
5
# Check for NXDOMAIN caching
dig nonexistent.example.com

# SOA MINIMUM field controls negative TTL
dig example.com SOA

CNAME chain too long:

1
2
3
4
# Follow CNAME chain
dig www.example.com +trace

# Most resolvers limit to 8-10 hops

Propagation delays:

1
2
3
4
5
# Check multiple DNS servers
for ns in 8.8.8.8 1.1.1.1 208.67.222.222; do
  echo "=== $ns ==="
  dig @$ns example.com +short
done

Online Tools

Security

DNSSEC

Cryptographic signatures prevent DNS spoofing:

1
2
3
4
5
# Check DNSSEC status
dig example.com +dnssec

# Verify chain of trust
delv example.com

Route 53 supports DNSSEC signing for public zones.

DNS over HTTPS/TLS

Encrypt DNS queries:

1
2
3
# DoH query
curl -H 'accept: application/dns-json' \
  'https://cloudflare-dns.com/dns-query?name=example.com&type=A'

Quick Reference

RecordPurposeExample
AIPv4 address93.184.216.34
AAAAIPv6 address2606:2800:...
CNAMEAlias (not at apex)www → example.com
MXMail server10 mail.example.com
TXTText dataSPF, DKIM, verification
CAACA authorizationissue "letsencrypt.org"
SRVService location_http._tcp...

Checklist

  • TTLs appropriate for record stability
  • Health checks on critical records
  • CAA records restrict certificate issuance
  • SPF/DKIM/DMARC for email
  • Internal DNS for private services
  • Monitoring for DNS resolution failures
  • DNSSEC enabled (if supported)

DNS problems look like everything-else problems. When debugging connectivity, check DNS first—it’s usually the culprit.