Reach a service privately on Google Cloud, without peering the networks
Six steps to a private path from a consumer workload to a producer service: decide endpoint or backend, reserve the consumer address, have the producer publish a service attachment with an accept list and NAT subnets, connect, allow the egress, then verify by proving the path is internal.
markdownguidev1ENA4-6BSKstage: buildtrust: officialfamily: networkingservice: private-service-connectinterface: anyprivate service connectendpointbackendservice attachmentaccept listNAT subnetinternal IP addressprivate accessVPC peering alternative
Reach a service privately
Use this instead of peering whenever the thing you need is a service, not a network. Peering joins whole address spaces, is not transitive, and fails outright on overlapping ranges; Private Service Connect joins one service to one internal address and does none of those things.
Step 1 — endpoint or backend
| Choose | When |
|---|---|
| endpoint | the workload just needs to call the service. One forwarding rule, one internal IP address. This is the default answer |
| backend | you want the service behind your own load balancer — so your own policies, including a Cloud Armor security policy on a regional internal Application Load Balancer, sit in front of it |
A backend is more objects and more control. Do not reach for it unless you want the load balancer for a reason you can name.
Step 2 — reserve the consumer-side address
An endpoint consumes an internal IP address from a subnet in the consumer's VPC network. Reserve it deliberately, in the subnet the calling workload lives in, and record it in the address plan.
At one or two connections this is invisible. At a hundred it is a real allocation, and it is the line most often missing from a migrated address plan.
Step 3 — the producer publishes a service attachment
On the producer side (which may be another team, or another company):
- a service attachment targeting the producer's load balancer;
- a consumer accept list — who is allowed to connect;
- NAT subnets for the translated traffic.
The accept list is the authorisation boundary. The consumer cannot connect without being on it, and the producer does not have to trust the consumer's network to let them in.
If the producer also needs to initiate calls into the consumer — a managed data plane reading a customer database — that is a producer-side interface, the reverse-direction object, and not a second endpoint.
Step 4 — connect, and confirm which object you got
The consumer creates the endpoint (or the backend) against the attachment. Confirm the connection's state on both sides before testing anything: a pending accept-list approval looks exactly like a network fault from the consumer's side.
Step 5 — allow the egress
Egress is implied-allow on a fresh VPC network, so this step is a no-op there. On a hardened network with explicit egress rules it is not: add the rule to the endpoint's address. This is the step people skip because it worked in the sandbox.
Step 6 — verify that the path is actually private
| Check | Expected |
|---|---|
| resolve and connect to the endpoint address from the consumer workload | success, on an internal address from your own subnet |
| confirm the workload needs no external IP and no NAT for this call | correct — the traffic stays within Google Cloud |
| remove the consumer from the accept list and retry | the connection fails |
The third row is the one that proves it. A path that still works after you revoke the authorisation was never going through the mechanism you think it was.
For a migration
This is the counterpart of AWS PrivateLink and Azure Private Link, and Microsoft's own mapping table pairs it
with Private Link. Designs port. What does not port automatically is the address plan: every private
connection consumes a consumer-side address on all three clouds. Count them before you commit a subnet
size. See guides/parity/networking.md.