SynfraCore
Synfracore
Start Learning
Navigation

Academies

Platform

RoadmapsLabsCertificationsInterviewPYQsAI AssistantCareer
Start Learning Free🗺️ Learning Roadmaps

Route53Fundamentals

Core concepts and commands — hands-on from the start

✍️
Written by senior engineers. Reviewed for technical accuracy.· Updated 2025 · SynfraCore Route53 Team
Expert Content

AWS Route53 — DNS and Traffic Management

The Hook

A DNS record is really just a lookup-table row: "for this name, answer with this value." Route 53 hosted zones are that lookup table, hosted on AWS's authoritative name servers. Everything else — weighted routing, health checks, failover — is Route 53 deciding WHICH row to return when there are multiple candidates for the same name, not a change to how DNS itself fundamentally works.

Analogy — A CNAME record is like telling someone "ask my assistant" — one more hop, one more lookup, before you get an answer. An ALIAS record (Route 53's own extension, not a standard DNS record type) is like the assistant being fused directly into your own desk — same one-hop convenience as an A record, but AWS transparently keeps the target IP up to date on your behalf, which is exactly why it's the only option that works at a domain's bare apex (example.com, not www.example.com) where a real CNAME is disallowed by the DNS standard.

Core Concepts

Route53 is AWS's DNS service + health checking + traffic routing

Record types:
  A:     Domain → IPv4 (192.0.2.1)
  AAAA:  Domain → IPv6
  CNAME: Domain → another domain (can't use for zone apex!)
  ALIAS: Like CNAME but works at apex (api.example.com → ALB)
  MX:    Mail exchange servers
  TXT:   SPF, DKIM, domain verification
  NS:    Nameservers (auto-managed by Route53)
  SOA:   Start of Authority (auto-managed)

Create Records with Terraform

hcl
resource "aws_route53_zone" "main" {
  name = "example.com"
}

# A record pointing to EC2
resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "www.example.com"
  type    = "A"
  ttl     = 300
  records = ["203.0.113.1"]
}

# ALIAS record for ALB (no TTL needed — AWS-managed)
resource "aws_route53_record" "api" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "api.example.com"
  type    = "A"

  alias {
    name                   = aws_lb.main.dns_name
    zone_id                = aws_lb.main.zone_id
    evaluate_target_health = true
  }
}

# Weighted routing — split traffic 90/10
resource "aws_route53_record" "blue" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "app.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
    evaluate_target_health = true
  }
}

resource "aws_route53_record" "green" {
  zone_id        = aws_route53_zone.main.zone_id
  name           = "app.example.com"
  type           = "A"
  set_identifier = "green"
  weighted_routing_policy {
    weight = 10
  }
  alias {
    name                   = aws_lb.green.dns_name
    zone_id                = aws_lb.green.zone_id
    evaluate_target_health = true
  }
}

Routing Policies

Simple:         Single record, all traffic goes there
Weighted:       Split traffic % between endpoints (A/B, canary deploys)
Latency-based:  Route to lowest-latency region for the user
Geolocation:    Route India traffic to ap-south-1, US to us-east-1
Geoproximity:   Route by distance, with bias adjustment
Failover:       Active/passive — primary unless health check fails
Multi-value:    Return multiple healthy IPs (basic load balancing)

Route53 Cheatsheet

bash
# ── CLI OPERATIONS ────────────────────────────────────────
aws route53 list-hosted-zones
aws route53 get-hosted-zone --id /hostedzone/ZXXXXX

# Create record (JSON change batch)
aws route53 change-resource-record-sets \
    --hosted-zone-id /hostedzone/ZXXXXX \
    --change-batch '{
        "Changes": [{
            "Action": "UPSERT",
            "ResourceRecordSet": {
                "Name": "api.example.com",
                "Type": "A",
                "TTL": 300,
                "ResourceRecords": [{"Value": "203.0.113.1"}]
            }
        }]
    }'

# Health checks
aws route53 create-health-check \
    --caller-reference "check-$(date +%s)" \
    --health-check-config '{
        "IPAddress": "203.0.113.1",
        "Port": 443, "Type": "HTTPS",
        "ResourcePath": "/health",
        "FullyQualifiedDomainName": "api.example.com",
        "RequestInterval": 30,
        "FailureThreshold": 3
    }'

aws route53 list-health-checks
aws route53 get-health-check-status --health-check-id XXXX

# DNS debugging
dig api.example.com @8.8.8.8
dig +trace api.example.com
nslookup api.example.com

Try It (2 Minutes)

If you have AWS CLI access to a sandbox account with a hosted zone, watch a change propagate:

bash
aws route53 change-resource-record-sets \
    --hosted-zone-id /hostedzone/ZXXXXX \
    --change-batch '{"Changes":[{"Action":"UPSERT","ResourceRecordSet":
    {"Name":"test.example.com","Type":"A","TTL":60,
    "ResourceRecords":[{"Value":"203.0.113.9"}]}}]}'
dig test.example.com   # should resolve within seconds — TTL 60 means clients
                         # (not Route 53 itself) will re-check it every 60s

No AWS access handy? Reason through it instead: dig +trace above walks from the root name servers down to the authoritative servers for a domain. At which specific step in that chain does Route 53 actually get consulted — and what would dig +trace show differently for a domain that DOESN'T use Route 53 at all?

Share:
Join our Community
Daily tips, job alerts, interview help — join engineers learning together
Up Next
Route53Intermediate
Real-world patterns, best practices, and deeper topics
Also Worth Exploring
← Back to all Route53 modules
InstallationIntermediate