Private Hosted Zones in AWS Route 53 Explained
A Route 53 private hosted zone is a DNS zone that resolves only inside the VPCs it is associated with. The records in it are invisible on the public internet. It gives your internal AWS resources stable, human-readable names: instead of scattering a long RDS endpoint string through every config file, every service in your VPC can reach the database at db.internal.example.com and nothing breaks when the endpoint changes.
Simple explanation
Think of a private hosted zone as a private phone book that only exists inside your building. A public hosted zone is the phone book the whole internet can look up. Your private book only works inside whichever VPCs you attach it to. Everyone outside sees nothing.
When an EC2 instance asks “where is db.internal.example.com?”, it asks the VPC’s built-in DNS resolver. That resolver checks the private hosted zone and returns the answer. No one outside the VPC gets the same answer, or any answer at all.
This is different from public DNS, which is how browsers on the internet find your website. Private hosted zones are for internal AWS workloads only: application servers finding their database, microservices finding each other, internal load balancers, and private endpoints for AWS services like S3 or Secrets Manager.
Why private hosted zones exist
Without private DNS, services inside a VPC reference each other by private IP address or by the AWS-assigned endpoint string like my-db.cluster-xyz.us-east-1.rds.amazonaws.com. Both approaches break in practice.
Private IP addresses change every time you recreate a resource. AWS endpoint strings are long, hard to read, tied to a specific resource, and embedded in configuration files across every service that uses them. When you replace an RDS instance or swap a load balancer, you update every caller.
Private hosted zones give you a stable layer of indirection. You point db.internal.example.com at your current RDS endpoint. When you replace the database, you update one DNS record. Every application using the DNS name picks up the change automatically without touching its own configuration. The same pattern applies to microservices discovering internal APIs, internal ALBs in private subnets, and any service-to-service communication that should stay off the public internet.
Private hosted zones also enable environment consistency. You can use the same internal DNS names across dev, staging, and production by giving each environment its own private hosted zone with the same structure but different record values. Promoting from dev to staging becomes a VPC association change, not a configuration rollout.
How private hosted zones work
A private hosted zone is structurally identical to a public hosted zone: same record types (A, CNAME, Alias, TXT, and so on), same TTL settings, same routing policies. The difference is that when you create it, you mark it private and associate it with one or more VPCs.
Every VPC has a built-in DNS resolver called the Route 53 VPC Resolver, reachable at the VPC’s base CIDR address plus two. For a VPC with the CIDR 10.0.0.0/16, the resolver is at 10.0.0.2. EC2 instances use this address for DNS by default (it is set automatically in the VPC’s DHCP options). You do not configure this manually.
When the VPC Resolver receives a query for a name in a private hosted zone associated with that VPC, it returns the record from the private zone. Queries from VPCs that are not associated with the zone get no response from the private zone.
Required VPC settings
Private hosted zones require both enableDnsSupport and enableDnsHostnames to be enabled on the VPC. Both are on by default for the default VPC. For custom VPCs, enableDnsHostnames is off by default, so you must enable it. If either setting is disabled, private hosted zone records will not resolve. See the DNS resolution troubleshooting guide for how to check and fix these settings.
When to use this
Use a private hosted zone whenever internal services need stable DNS names that should not be visible on the public internet.
Internal database names: Point db.internal.example.com at your RDS cluster endpoint. Applications use the DNS name. When you replace the database, you update one record.
Internal load balancers and microservices: Register each microservice under a readable name in the private zone (payments.internal.example.com, orders.internal.example.com). Services find each other by name, not by ALB DNS string.
Multi-VPC internal naming: Associate the private hosted zone with multiple VPCs so all your environments can resolve the same internal names. Useful when you have separate VPCs for dev, staging, and production.
Hybrid and on-premises connectivity: If you have on-premises servers connected via Site-to-Site VPN or Direct Connect, you can configure Route 53 Resolver Inbound Endpoints so those servers can resolve names in your private hosted zone. See the hybrid connectivity overview for the broader picture.
Private endpoints for AWS services: When you create Interface VPC Endpoints for services like S3, Secrets Manager, or SSM using AWS PrivateLink, those endpoints come with private DNS options. Traffic to the service stays on the AWS network and is resolved through the private hosted zone. See VPC endpoint policies for how to control access to these endpoints.
Good starting point
If you are not sure which domain name to use, a common convention is internal.yourdomain.com for AWS-only workloads and corp.yourdomain.com for names that also need to resolve from on-premises. Keep it separate from your public zone apex to avoid accidental split-horizon surprises.
When not to use this
Do not create a private hosted zone for domains that only need public resolution. If your website or API is purely public-facing, a standard Route 53 public hosted zone is the right tool.
Avoid using private hosted zones for the same domain apex as your public zone unless you fully understand split-horizon DNS. If you create example.com as a private zone but forget to add a record for www.example.com, resources inside your VPC will get NXDOMAIN for www.example.com, even though the public zone has that record. There is no fallback.
If your goal is to forward DNS queries from on-premises to AWS without managing a full private hosted zone, consider Route 53 Resolver forwarding rules instead. They let you forward specific domains to custom DNS servers without duplicating zone management. Forwarding rules take precedence over private hosted zones for the same domain, so if you use both, understand the precedence order.
How it works step by step
Here is what happens when an EC2 instance queries a name in a private hosted zone:
- The EC2 instance queries
db.internal.example.com. - The query goes to the VPC Resolver at
10.0.0.2(base CIDR + 2). - The Resolver checks whether a private hosted zone associated with this VPC is authoritative for
internal.example.com. - It finds the private zone and looks up the
db.internal.example.comrecord. - The record exists: a CNAME pointing to the RDS cluster endpoint.
- The Resolver returns the answer. The EC2 instance connects to the database.
If the private zone is associated but the record is missing, step 5 fails. The Resolver returns NXDOMAIN. It does not fall through to check a public hosted zone with the same name. The private zone’s authority over that domain is absolute inside the VPC.
Creating a private hosted zone
You create a private hosted zone with the Route 53 console or CLI. The key difference from a public zone is the PrivateZone=true flag and the VPC association at creation time.
# Create a private hosted zone associated with a VPC
aws route53 create-hosted-zone \
--name internal.example.com \
--caller-reference "private-hz-$(date +%s)" \
--hosted-zone-config PrivateZone=true \
--vpc VPCRegion=us-east-1,VPCId=vpc-0abc123def456789a
# Save the hosted zone ID from the output
# "Id": "/hostedzone/Z9876543210ZYXWV9876"Once the zone exists, add records for the internal services you want reachable by name:
# Add a CNAME pointing db.internal.example.com to an RDS endpoint
aws route53 change-resource-record-sets \
--hosted-zone-id Z9876543210ZYXWV9876 \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "db.internal.example.com",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [{
"Value": "my-db.cluster-xyz.us-east-1.rds.amazonaws.com"
}]
}
}]
}'
# Add an Alias A record pointing api.internal.example.com to an internal ALB
aws route53 change-resource-record-sets \
--hosted-zone-id Z9876543210ZYXWV9876 \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "api.internal.example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z35SXDOTRQ7X7K",
"DNSName": "internal-alb-123456.us-east-1.elb.amazonaws.com",
"EvaluateTargetHealth": true
}
}
}]
}'Associating multiple VPCs
A private hosted zone can be associated with any number of VPCs. Records resolve correctly inside any associated VPC. This is useful for multi-VPC architectures: separate VPCs for different environments or teams that all need to resolve the same internal DNS names.
# Associate an additional VPC in the same account
aws route53 associate-vpc-with-hosted-zone \
--hosted-zone-id Z9876543210ZYXWV9876 \
--vpc VPCRegion=us-east-1,VPCId=vpc-0def456abc123789bFor cross-account associations, the process takes two steps: the hosted zone owner creates an authorization for the other account’s VPC, and the VPC owner completes the association from their account.
# Step 1: Hosted zone owner account: authorize the cross-account VPC
aws route53 create-vpc-association-authorization \
--hosted-zone-id Z9876543210ZYXWV9876 \
--vpc VPCRegion=us-east-1,VPCId=vpc-crossaccount
# Step 2: VPC owner account: complete the association
aws route53 associate-vpc-with-hosted-zone \
--hosted-zone-id Z9876543210ZYXWV9876 \
--vpc VPCRegion=us-east-1,VPCId=vpc-crossaccountSplit-horizon DNS
Split-horizon (or split-view) DNS means the same domain name resolves to different answers depending on where the query originates. Private hosted zones make this straightforward: create a private zone and a public zone with the same name, put different records in each, and Route 53 serves the right answer based on whether the query comes from inside or outside an associated VPC.
A common use case: api.example.com should resolve to a public ALB for internet users, but to an internal ALB for services running inside your VPC. This avoids the unnecessary public internet round-trip. The public hosted zone has an A record pointing to the public ALB. The private hosted zone has an Alias record pointing to the internal ALB. Inside the VPC, the private answer wins every time.
Watch out: NXDOMAIN trap
When a private hosted zone is authoritative for a domain inside an associated VPC, Route 53 does not fall back to the public zone for any name, even names that only exist in the public zone. If example.com is your private zone and you query mail.example.com from inside the VPC, but that record is only in the public zone, you get NXDOMAIN. The private zone wins, and the answer is “not found.” Add every record your VPC resources need to the private zone, or avoid using the same domain apex for both public and private zones unless you manage them together deliberately.
Private hosted zones vs public hosted zones vs Resolver forwarding
| Private hosted zone | Public hosted zone | Resolver forwarding rule | |
|---|---|---|---|
| Who can query it | Only from associated VPCs | Anyone on the internet | Only from associated VPCs |
| Records managed by | You, in Route 53 | You, in Route 53 | External or custom DNS server (forwarded to) |
| Primary use case | Internal service discovery inside AWS | Public-facing websites and APIs | Forwarding queries to on-premises or custom DNS |
| Precedence inside VPC | Wins over public zone for same domain | Loses to private zone inside associated VPC | Takes precedence over private hosted zones for same domain |
| Common mistake | Missing records cause NXDOMAIN with no public fallback | Using for internal-only names that should stay private | Forwarding rule overrides private zone unexpectedly |
Resolver rule precedence If you have both a private hosted zone and a Resolver forwarding rule configured for the same domain in a VPC, the forwarding rule takes precedence. DNS queries go to the forwarding target, not the private hosted zone. If private zone records stop resolving unexpectedly, check whether a Resolver rule is intercepting the traffic first.
Resolving private DNS from on-premises
On-premises servers cannot query Route 53 private hosted zones directly. The Route 53 VPC Resolver at base+2 is only reachable from inside the VPC, so it is not accessible to traffic coming in over a VPN or Direct Connect link.
To allow on-premises servers to resolve names in a private hosted zone, you create a Route 53 Resolver Inbound Endpoint. The endpoint deploys a pair of DNS resolver IPs inside your VPC as Elastic Network Interfaces in subnets you specify. You then configure your on-premises DNS server to forward queries for your internal domain to those IP addresses. The endpoint receives the queries, resolves them using the VPC Resolver (which can see private hosted zones), and returns the answers back to the on-premises server through your hybrid connectivity link.
# Create a Route 53 Resolver Inbound Endpoint
aws route53resolver create-resolver-endpoint \
--creator-request-id "inbound-$(date +%s)" \
--direction INBOUND \
--security-group-ids sg-resolver-endpoint \
--ip-addresses \
SubnetId=subnet-private-az1,Ip=10.0.1.100 \
SubnetId=subnet-private-az2,Ip=10.0.2.100
# Then configure your on-premises DNS server to forward
# queries for internal.example.com to 10.0.1.100 and 10.0.2.100Always use two IPs in two different Availability Zones. If one AZ has an issue, DNS forwarding continues through the other endpoint IP. Ensure your security group allows UDP and TCP on port 53 from your on-premises IP range.
Common mistakes
- VPC not associated with the private hosted zone. A private hosted zone that is not associated with a VPC is invisible from that VPC. Open the Route 53 console, find the hosted zone, and check the list of associated VPCs. This is the single most common cause of private zone resolution failures.
- enableDnsSupport or enableDnsHostnames not enabled. Custom VPCs have
enableDnsHostnamesdisabled by default. Private hosted zones require both settings to be on. Check and enable them via the VPC console or CLI. The DNS resolution troubleshooting guide shows the exact commands. - Expecting fallback to public DNS when a record is missing. If a private zone is associated with your VPC and is authoritative for a domain, Route 53 does not fall back to the public zone for missing records. A missing record returns NXDOMAIN. Add the record to the private zone or do not use the private zone for that domain.
- Using the same domain for both private and public zones without managing every record in both. Split-horizon DNS is useful, but it requires that the private zone contains every record your VPC workloads need. A partial private zone silently breaks resolution for any name that exists only in the public zone.
- Custom DNS servers not forwarding to the Route 53 Resolver. If you use a custom DHCP option set to point instances at a custom DNS server (such as Active Directory DNS), that server must forward AWS-internal names to the VPC Resolver at
base+2. If it does not, private hosted zones and AWS service endpoints stop resolving. - Resolver rule precedence confusion. If you create a Resolver forwarding rule for a domain that also has a private hosted zone, the forwarding rule wins. Queries go to the forwarding target instead of the private hosted zone. Check your Resolver rules if private zone records stop resolving unexpectedly.
Troubleshooting checklist
When a private hosted zone record is not resolving from inside your VPC, work through these checks in order:
- Does the record exist? Open Route 53 and confirm the record is in the correct hosted zone with the correct name and type.
- Is the hosted zone associated with the correct VPC? Check the hosted zone’s VPC associations. The VPC must be explicitly listed; there is no default association.
- Are VPC DNS settings enabled? Run
describe-vpc-attributefor bothenableDnsSupportandenableDnsHostnames. Both must returntrue. - Is the instance using the VPC Resolver? On a Linux instance, check
/etc/resolv.conf. It should list thebase+2address. A custom DHCP option set may have overridden it with a different DNS server. - Is a custom DNS server intercepting the query? If so, confirm it forwards to the VPC Resolver for AWS-internal names. It should not attempt to resolve private hosted zone names externally.
- Are there Resolver forwarding rules for the same domain? Check Route 53 Resolver rules. A forwarding rule for the same domain takes precedence over the private hosted zone.
- Are you testing from the right network context? Private zone records only resolve from inside an associated VPC. Testing from your laptop will correctly return no result, which is expected behavior.
- For cross-account associations: Confirm the authorization exists in the hosted zone owner account and the association was completed from the VPC owner account.
For a deeper look at VPC DNS failures and their fixes, see the DNS resolution problems guide.
Summary
- A private hosted zone resolves DNS names only within its associated VPCs. Records are invisible on the public internet.
- The VPC Resolver at
base CIDR + 2handles queries and looks up records in associated private hosted zones automatically. - Both
enableDnsSupportandenableDnsHostnamesmust be enabled on the VPC for private hosted zones to work. - Private zones take absolute precedence over public zones inside associated VPCs. There is no fallback if a record is missing. A missing record returns NXDOMAIN.
- Split-horizon DNS gives internal and external clients different answers for the same domain name. Manage it carefully to avoid NXDOMAIN surprises inside the VPC.
- Resolver forwarding rules take precedence over private hosted zones for the same domain. Check your rules if private zone records stop resolving unexpectedly.
- On-premises servers can query private hosted zones via Route 53 Resolver Inbound Endpoints, with DNS forwarding configured on the on-premises DNS server.
- Cross-account VPC associations are supported with a two-step authorization and association flow.
Frequently asked questions
Can internet users query a private hosted zone?
No. Private hosted zones respond only to DNS queries that originate from within the VPCs they are associated with. A query from the public internet, from an on-premises server, or from a VPC that is not associated with the zone returns no result. The records are invisible outside the associated VPCs.
What happens if I have both a public and private hosted zone for the same domain name?
Inside a VPC associated with the private zone, the private zone always wins. Route 53 returns the private zone records regardless of what the public zone contains. The critical trap: if the private zone exists but is missing a specific record, Route 53 returns NXDOMAIN rather than falling through to the public zone. Every name your VPC resources need must exist in the private zone.
Can I associate a private hosted zone with VPCs in different AWS accounts?
Yes. Cross-account associations are supported. The hosted zone owner account creates an association authorization for the other account VPC. The VPC owner account then completes the association. Once done, resources in that VPC can resolve records from the private hosted zone just like same-account VPCs.
Why am I getting NXDOMAIN for a record I know exists?
The most common causes: the VPC is not associated with the private hosted zone; the record exists in a public zone but not in the private zone (and the private zone blocks fallback); enableDnsSupport or enableDnsHostnames is disabled on the VPC; or a custom DNS server is not forwarding to the Route 53 Resolver at the VPC base address plus 2. Check each of these in order.
Do I need Route 53 Resolver endpoints to use private hosted zones from on-premises?
Yes. On-premises servers cannot directly reach the Route 53 Resolver at your VPC base address plus 2 because it is not accessible from outside the VPC. You deploy a Route 53 Resolver Inbound Endpoint inside your VPC, then configure your on-premises DNS server to forward queries for your internal domain to the endpoint IPs. Those queries are resolved against the private hosted zone.