Route 53 Private Hosted Zones and VPC Peering can be confusing because their resolution mechanisms aren’t immediately obvious when you first encounter them.
Let’s look at a concrete example of what this looks like in practice. Imagine you have two VPCs, vpc-a and vpc-b, and you’ve peered them together. In vpc-a, you have a private hosted zone named mycorp.local registered with Route 53. This zone contains an A record for db.mycorp.local pointing to 10.0.1.10.
Here’s how you might set up the private hosted zone and associate it with vpc-a:
{
"Comment": "Create a private hosted zone",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "mycorp.local.",
"Type": "NS",
"TTL": 172800,
"ResourceRecords": [
{ "Value": "ns-1234.awsdns-56.com." },
{ "Value": "ns-5678.awsdns-12.net." },
{ "Value": "ns-9012.awsdns-34.org." },
{ "Value": "ns-3456.awsdns-01.co.uk." }
]
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "mycorp.local.",
"Type": "SOA",
"TTL": 900,
"ResourceRecords": [
{ "Value": "ns-1234.awsdns-56.com. awsdns-admin.amazon.com. 1 7200 900 1209600 86400" }
]
}
}
]
}
And the association with vpc-a:
aws route53 associate-vpc-with-hosted-zone \
--hosted-zone-id Z1A2B3C4D5E6F7 \
--vpc-id vpc-a1b2c3d4 \
--vpc-region us-east-1
Now, from an EC2 instance within vpc-a, you can dig db.mycorp.local and get 10.0.1.10. This works because the EC2 instance’s DNS resolver is configured to query Route 53 for mycorp.local.
The real magic happens when you want to resolve db.mycorp.local from an instance in vpc-b. For this to work, you need to establish VPC peering and then associate the same private hosted zone (mycorp.local) with vpc-b as well.
Here’s the crucial part: VPC peering allows network traffic to flow between the two VPCs, but it doesn’t automatically extend DNS resolution. You must explicitly tell Route 53 that vpc-b should also be able to resolve names within mycorp.local.
Once mycorp.local is associated with vpc-b:
aws route53 associate-vpc-with-hosted-zone \
--hosted-zone-id Z1A2B3C4D5E6F7 \
--vpc-id vpc-b5c6d7e8 \
--vpc-region us-west-2
An EC2 instance in vpc-b can now dig db.mycorp.local and correctly resolve 10.0.1.10. The EC2 instance in vpc-b will query its default DNS resolver (which is 169.254.169.253 in Amazon Linux, for example). This resolver, seeing that mycorp.local is a private zone associated with vpc-b, forwards the query to Route 53. Route 53, knowing that mycorp.local is associated with vpc-b (and has the record), returns the IP address. The peering connection is what allows the DNS query packets to travel from vpc-b to the Route 53 resolver endpoint associated with vpc-b (which is implicitly managed by AWS).
The mental model is that a private hosted zone is tied to specific VPCs. When you associate a zone with a VPC, you’re essentially creating an "entry point" for DNS queries within that VPC to reach Route 53 for names within that zone. VPC peering is a network connectivity layer; it doesn’t inherently enable cross-VPC DNS resolution unless Route 53 is configured to allow it through zone associations.
A common misconception is that simply peering VPCs is enough for DNS resolution. However, Route 53 operates independently of the VPC peering connection itself. The peering connection only enables the traffic to flow; the private hosted zone association is what enables the DNS resolution logic to be applied to that traffic for specific zones. Without associating the zone with vpc-b, an EC2 instance in vpc-b would get an NXDOMAIN response or a timeout when trying to resolve db.mycorp.local.
The resolution mechanism for a private hosted zone associated with multiple VPCs relies on the VPC’s DNS resolver forwarding queries to Route 53. When Route 53 receives a query for a name within a private hosted zone, it checks which VPCs are associated with that zone. If the originating VPC (from which the query came) is one of those associated VPCs, Route 53 then looks up the record within the zone and returns the answer. The peering connection is what allows the initial query from vpc-b to reach the Route 53 service that’s aware of vpc-b’s association with mycorp.local.
The next thing you’ll likely run into is how to handle DNS resolution when you have transitive VPC peering, or when you need to resolve names in a peered VPC’s public hosted zone from within your private hosted zone.