GCP Private DNS Zones | Internal DNS Resolution in Google Cloud
A private DNS zone in GCP resolves names only inside the VPCs you attach it to. It gives your internal services human-readable names without exposing them to the public internet, so your apps can connect to a database by name instead of by IP, and you can change the underlying IP without touching application config.
What is a private DNS zone?
In public DNS, anyone in the world can look up a hostname and get an answer. A private DNS zone works differently: it is only visible inside the VPCs you authorise. Queries from outside those networks get no response.
You define records just like you would in a public zone. For example, you might create an A record for postgres.internal.example.com that points to a Cloud SQL private IP, or a record for redis.cache.internal that points to a Memorystore instance. Apps inside the VPC resolve those names through the VPC resolver without any extra configuration. Nothing outside the VPC sees the records.
Private zones are managed through Cloud DNS and attach to one or more VPCs. The VPC resolver at 169.254.169.254 handles the lookup for any name that matches the zone’s domain suffix.
A private DNS zone is like a company’s internal phone directory. It lists extensions that only make sense inside the building. If someone outside tries to look them up in the public directory, they find nothing. The directory is invisible to the outside world by design.
Why private DNS zones matter
Without a private zone, you have two options for internal service connectivity: hardcode IP addresses in your application config, or maintain manual hosts files on every VM. Both create operational problems.
Private zones eliminate those problems by giving you a single place to manage internal name-to-IP mappings. The practical benefits are real:
- No hardcoded IPs. Apps connect to
db.internal.example.comrather than10.10.0.5. When the database is migrated or recreated, you update one DNS record rather than every app that connects to it. - Easier service discovery. Services can find each other by stable, meaningful names rather than IPs that change when resources are replaced.
- Cleaner access control. You can give a name only to VMs in the VPCs that need it, keeping internal services invisible to everything else.
- Simpler migrations. Moving a service to a new IP becomes a DNS update with a short TTL rather than a coordinated app deployment.
Private zones also let you override public DNS names inside the VPC, which is the key mechanism for routing Google API traffic through private endpoints when you are using Private Google Access or VPC Service Controls.
How private DNS zones work in GCP
When you create a private zone in Cloud DNS, you attach it to one or more VPCs. These are called authorised networks. VMs in those VPCs send DNS queries to the VPC resolver at 169.254.169.254. The resolver checks whether any private zone matches the query name and, if so, returns the answer from that zone. Public DNS is only consulted if no private zone matches.
A few details that matter in practice:
- Private zones take precedence over public DNS for names that match. This is how overriding
googleapis.comworks: you create a private zone for that suffix, and the VPC resolver serves your records instead of the public ones. - Custom DNS servers you run yourself (such as BIND on a VM) do not automatically inherit private Cloud DNS zones. If you use custom DNS servers, configure them to forward unmatched queries to the VPC resolver so they can still reach your private zones.
- A private zone can be attached to multiple VPCs. VMs in any of the authorised VPCs can resolve names from the same zone without you duplicating records.
The VPC resolver uses longest-suffix matching. If you have a zone for internal.example.com and another for example.com, a query for db.internal.example.com is handled by the more specific zone. The more specific match always wins.
This resolver behaviour is covered in more depth on the DNS in GCP page.
When to use private DNS zones
Private zones are the right tool in these situations:
- Internal app-to-database connectivity. Give Cloud SQL, Memorystore, or self-managed databases a stable DNS name that apps can use regardless of the underlying IP.
- Internal service discovery. Microservices that communicate inside a VPC can find each other by name rather than by IP or service registries.
- Shared services VPCs. A zone attached to a shared services VPC lets other VPCs resolve those names via DNS peering, without duplicating records. This is a common pattern in Shared VPC setups.
- Hybrid connectivity. On-premises services can be given names in a private zone, or GCP names can be forwarded to on-premises DNS when the on-premises DNS system is authoritative. See Cloud VPN and Cloud Interconnect for the connectivity layer.
- Private Google Access. Override
googleapis.cominside the VPC to route API traffic through private VIPs. Required when enforcing VPC Service Controls.
Private DNS zones vs forwarding zones
Both are private in the sense that they only apply inside authorised VPCs. The difference is where the records live.
| Feature | Private managed zone | Forwarding zone |
|---|---|---|
| Where records live | In Cloud DNS, managed by you | On an external DNS server you specify |
| What Cloud DNS does | Resolves queries directly | Forwards queries to the external server |
| Typical use case | New internal names, overrides | On-premises domains already served by another DNS |
| Requires external DNS server | No | Yes |
| Records managed in | Cloud DNS console or gcloud | Your external DNS server |
Choose a private managed zone when Cloud DNS should be the authoritative source for those names. Choose a forwarding zone when another DNS server already owns those names and Cloud DNS should delegate to it. In hybrid environments, you often have both: a private zone for GCP-native names and a forwarding zone to reach on-premises hostnames.
Think of a forwarding zone as a reception desk that transfers calls it cannot handle. The receptionist does not have the answer, but they know which office to send the caller to. A private managed zone is the office that actually has the answers.
When creating a forwarding zone to reach on-premises DNS servers over Cloud VPN or Interconnect, always use —private-forwarding-targets rather than —forwarding-targets. Standard forwarding targets route the forwarded packet over the public internet, which cannot reach a server that has no public IP. This is one of the most common setup mistakes in hybrid DNS configurations.
# Forwarding zone that sends corp.internal queries to an on-premises DNS server
# Use --private-forwarding-targets for servers behind VPN or Interconnect
gcloud dns managed-zones create corp-internal-fwd \
--dns-name=corp.internal. \
--description="Forward corp.internal to on-premises DNS" \
--visibility=private \
--networks=my-vpc \
--private-forwarding-targets=10.0.0.53Private DNS zones vs DNS peering
DNS peering is a separate Cloud DNS feature that lets one VPC resolve names from private zones attached to another VPC. It often gets confused with VPC network peering because both involve two VPCs, but they are independent features.
VPC network peering connects networks at the routing level so that traffic can flow between them. It does not share DNS. A VM in a peered VPC still cannot resolve names from the other VPC’s private zones unless you configure DNS peering explicitly.
DNS peering is useful when you have a private zone in one VPC and want VMs in another VPC to resolve names from it, without duplicating the records. A common setup is a shared services VPC that owns the DNS zone, with application VPCs using DNS peering to read from it. You configure a peering zone in the consumer VPC that delegates queries for the relevant suffix to the producer VPC’s Cloud DNS server.
# DNS peering zone in vpc-a that delegates shared.internal
# queries to the Cloud DNS server of the shared-services project
gcloud dns managed-zones create shared-internal-peering \
--dns-name=shared.internal. \
--description="DNS peering to shared services VPC" \
--visibility=private \
--networks=vpc-a \
--dns-peer-project=shared-services-project \
--dns-peer-managed-zone=shared-internal-zoneVPC network peering and DNS peering are separate. Network peering gives you routing between VPCs. It does not give you name resolution across the boundary. If you only configure network peering, VMs in the peered VPC will fail to resolve names from the other side’s private zones. You need both features configured if you want both routing and DNS to work across the peering relationship.
Common setup patterns
Internal names for a single VPC
The simplest case: you have one VPC and want internal names for databases, caches, or APIs. Create a private zone for a domain like internal.example.com, attach it to your VPC, and add records. Apps in the VPC resolve those names through the VPC resolver without any additional configuration.
Shared services VPC
In a Shared VPC architecture, a shared services VPC often hosts central infrastructure like databases, monitoring agents, or build systems. Create the private zone in the shared services VPC and configure DNS peering in each application VPC so their VMs can resolve the shared service names without duplicating the zone everywhere.
Hybrid on-premises and GCP
In hybrid environments connected over Cloud VPN or Interconnect, you typically need name resolution to work in both directions:
- GCP VMs resolving on-premises names: create a forwarding zone in Cloud DNS that forwards queries for the on-premises domain to your on-premises DNS servers.
- On-premises VMs resolving GCP names: configure your on-premises DNS servers to forward queries for the GCP domain to the inbound DNS policy IP in your VPC.
See the DNS in GCP page for how inbound forwarding policies work.
Overriding googleapis.com for Private Google Access
This is an advanced pattern, but a required one when you are using Private Google Access with VPC Service Controls. VMs with no external IP need to reach Google APIs through private VIPs. Without a DNS override, the VPC resolver returns public Google API IPs and traffic goes over the internet rather than staying inside the VPC perimeter.
You fix this by creating a private zone for googleapis.com that returns the private VIP addresses instead. Which VIP depends on your setup:
private.googleapis.com(199.36.153.4/30): for Private Google Access without VPC Service Controls enforcementrestricted.googleapis.com(199.36.153.8/30): required when enforcing VPC Service Controls, as it ensures perimeter checks are applied
If you are using VPC Service Controls, you must use restricted.googleapis.com (199.36.153.8/30), not private.googleapis.com. The private VIP allows traffic to reach Google APIs but does not enforce VPC-SC perimeter checks, which creates an unintended data path that your perimeter is supposed to close. Getting this wrong is a silent security misconfiguration.
See the Private Google Access page for the full setup including firewall rules and routes.
Step-by-step: creating a private zone and adding a record
This example creates a private zone for internal.example.com, attaches it to a VPC, and adds an A record for a database.
# 1. Create the private zone attached to my-vpc
gcloud dns managed-zones create internal-example \
--dns-name=internal.example.com. \
--description="Private zone for internal services" \
--visibility=private \
--networks=my-vpc
# 2. Verify the zone was created correctly
gcloud dns managed-zones describe internal-example
# 3. Add an A record pointing postgres to a Cloud SQL private IP
gcloud dns record-sets create postgres.internal.example.com. \
--zone=internal-example \
--type=A \
--ttl=300 \
--rrdatas=10.10.0.5
# 4. Confirm the record exists
gcloud dns record-sets list --zone=internal-exampleAfter this, any VM inside my-vpc can resolve postgres.internal.example.com and get back 10.10.0.5. VMs outside the VPC get no answer. If the database IP changes, update the A record and the change propagates on the next TTL expiry. No application config changes needed.
To attach a private zone to an additional VPC after creation, use gcloud dns managed-zones update internal-example —add-networks=other-vpc. The zone’s records then resolve from both VPCs.
If you run into DNS resolution problems after creating a zone, the troubleshooting network issues guide covers how to diagnose DNS failures from inside a VM.
Common mistakes
- Creating a private zone but not attaching it to the correct VPCs. A private zone with no authorised networks resolves for nobody. Always check the
—networksflag when creating the zone. VMs in VPCs that are not listed simply do not see the zone and fall through to public DNS, which usually returns no result for an internal name. - Assuming VPC network peering automatically shares DNS. VPC network peering handles routing, not DNS. VMs in peered VPCs cannot resolve names from private zones on the other side unless you configure DNS peering separately. Both features need to be in place if you want both routing and name resolution to cross the peering boundary.
- Using standard forwarding targets instead of private forwarding targets for on-premises DNS. When your on-premises DNS server is reachable only over VPN or Interconnect, use
—private-forwarding-targetsin your forwarding zone. Standard—forwarding-targetsroutes the forwarded query over the default internet path, which cannot reach a server that has no public IP. - Expecting custom DNS servers to inherit Cloud DNS private zones automatically. If you run your own DNS server (such as BIND or Unbound on a VM), it does not get private zones from Cloud DNS by default. Configure your custom DNS server to forward queries it cannot resolve to the VPC resolver IP so it can still reach private zones.
- Using the wrong VIP when overriding googleapis.com for VPC Service Controls. If you are enforcing VPC Service Controls, you must point the override to
restricted.googleapis.com(199.36.153.8/30), notprivate.googleapis.com. The restricted VIP enforces perimeter checks. The private VIP does not, which means traffic reaches Google APIs but bypasses your VPC-SC perimeter. - Not overriding googleapis.com at all when using VPC Service Controls. Without a private zone override for
googleapis.com, VMs resolve Google API names to public IPs. Traffic to public IPs bypasses the VPC-SC perimeter entirely. The override is a required part of any VPC-SC setup, not optional.
Summary
- A private DNS zone resolves only inside the VPCs you attach it to and is invisible to the public internet
- Use private zones to give internal services stable, human-readable names instead of hardcoding IPs in application config
- Private zones take precedence over public DNS for names that match, which is the mechanism behind the googleapis.com override for Private Google Access
- Forwarding zones forward queries to external DNS servers. Choose them when another DNS system is already authoritative for a domain
- DNS peering and VPC network peering are separate features. Network peering does not share DNS, and you must configure DNS peering explicitly to cross VPC boundaries
- When using VPC Service Controls, override googleapis.com to restricted.googleapis.com (199.36.153.8/30). Using the private VIP or no override at all leaves the perimeter incomplete
- Custom DNS servers on VMs do not automatically inherit Cloud DNS private zones. Forward unmatched queries to the VPC resolver to bridge the two
Frequently asked questions
What is a private DNS zone in GCP?
A private DNS zone is a Cloud DNS managed zone that only resolves from within the VPCs you attach it to. It is not visible on the public internet. You use it to give internal resources human-readable names, such as pointing postgres.internal.example.com to a Cloud SQL private IP, without those names being resolvable by anyone outside your network.
Are private DNS zones accessible from the internet?
No. A private DNS zone only resolves for VMs that use the VPC resolver inside an authorised VPC. Queries from outside those VPCs get no response from the private zone. The records remain completely internal.
What is the difference between a private zone and a forwarding zone?
A private managed zone stores DNS records in Cloud DNS and resolves them directly. A forwarding zone does not store records. Instead, it forwards queries for a domain to external DNS servers you specify, such as on-premises servers reachable over Cloud VPN or Interconnect. Choose a private zone when you want Cloud DNS to be authoritative, and a forwarding zone when another DNS server is already authoritative.
Do private DNS zones work across VPC peering automatically?
No. VPC network peering connects networks at the routing level but does not share private DNS zones. A VM in a peered VPC cannot resolve names from the other VPC private zones unless you configure DNS peering separately in Cloud DNS. The two features are independent and both must be configured explicitly.
When should I override googleapis.com in a private zone?
You need a private zone for googleapis.com when using VPC Service Controls or Private Google Access in a restricted configuration. Without it, VMs resolve Google API hostnames to public IPs and traffic bypasses your VPC perimeter. If you are enforcing VPC Service Controls, override googleapis.com to point to restricted.googleapis.com (199.36.153.8/30). If you just need Private Google Access without VPC-SC, private.googleapis.com (199.36.153.4/30) is sufficient.