Business Challenge
Shared VPC has been a footnote in three of the last four posts — whose project the firewall logs name, which project flow logs are reported in, which project pays. This post is the model itself. Shared VPC allows an organization to connect resources from multiple projects to a common Virtual Private Cloud (VPC) network so that they can communicate with each other securely and efficiently by using internal IP addresses from that network. Structurally: when you use Shared VPC, you designate a project as a host project and attach one or more other service projects to it, and the VPC networks in the host project are called Shared VPC networks.
The purpose is a separation of duties, stated plainly: Shared VPC Admins can delegate network administration tasks to Network and Security Admins in the Shared VPC network without allowing Service Project Admins to make network-impacting changes. What surprised me is how much narrower the model is than that description suggests, and how much of it is prospective-only.
You cannot. A project cannot be both a host project and a service project simultaneously. And therefore: thus, a service project cannot be a host project to further service projects. The fan-in is capped too — you can create and use multiple host projects; however, each service project can only be attached to a single host project, and the quota page is unambiguous that this one is fixed: number of host projects to which a service project can attach 1, where this limit can't be increased.
Correct approachDesign it flat. Multiple host projects are supported — up to number of Shared VPC host projects in a single organization 100 — but each one is a separate island with its own set of service projects. A workload that genuinely needs two networks needs two interfaces or a peering, not a second attachment.
Nothing moved. When a Shared VPC Admin attaches an existing project, that project becomes a service project, but its existing resources do not automatically use shared network resources. Nor can they be migrated in place: an existing instance in a service project cannot be reconfigured to use a Shared VPC network, but a new instance can be created to use available subnets in a Shared VPC network. The documentation generalises it — some resources must be re-created in order to use a Shared VPC network — and names one more case: this limitation applies to private zones.
Correct approachTreat adoption as a rebuild, not a configuration change, and plan the replacement of every instance and private zone that is meant to end up on the shared network. The attachment is the cheap part; it is also the part that produces no visible progress.
It governs only what happens next. For host-project restrictions, the constraint doesn't affect existing attachments, and existing attachments remain intact even if a policy denies new ones. For subnet restrictions, the same shape: existing VMs and load balancers continue to operate normally in their subnets even if a policy prevents new resources from being added. There is also a named hole — forwarding rules that are used for Private Service Connect endpoints aren't restricted by this constraint.
Correct approachSet the constraint to stop the problem growing, then run a separate inventory to find and fix what predates it. A policy that reports no violations is telling you about attempts, not about state — which is the same distinction #75 ran into with insights and #77 with sampling.
Architecture
One project owns the network, several borrow its subnets, and four roles divide the work between them.
The boundaries it will not cross
Three constraints fix the shape. The organization is the hard edge: Shared VPC connects projects within the same organization, and participating host and service projects cannot belong to different organizations. There is exactly one documented exception, and it is temporary: during the migration, service projects can be in a different organization than the host project temporarily.
Folders are softer but not free. Linked projects can be in the same or different folders , but if they are in different folders the admin must have Shared VPC Admin rights to both folders. That is a real organisational constraint rather than a technical one — it means the person who attaches a project across a folder boundary must hold authority on both sides of it, which is usually a deliberate escalation.
And the network itself must be modern: Shared VPC networks can be either auto or custom mode , but legacy networks are not supported. That is the third post this week where legacy networks are excluded outright, which is as close to a deprecation as the documentation gets.
The vocabulary is worth adopting because the documentation uses it consistently: a project that does not participate in Shared VPC is called a standalone project. And one naming oddity that will save you a confused search — Shared VPC is also referred to as "XPN" in the API, which is why the admin role is compute.xpnAdmin rather than anything containing the words "shared" or "VPC".
Two sharing scopes, and the one that keeps growing
When a host project is enabled there is a choice that looks administrative and is actually a security posture. The broad option: you can share all host project subnets, and the consequence is explicit — if you select this option, then any new subnets created in the host project, including subnets in new networks, will also be shared. The narrow option: if you share subnets individually, then only those subnets are shared unless you manually change the list.
The same fork appears again one level down, in IAM. A project-level grant of compute.networkUser means the Service Project Admin has permission to use all subnets in all VPC networks of the host project, including subnets and VPC networks added to the host project in the future, where a subnet-level grant means a Service Project Admin who only has subnet-level permissions is restricted to using only those subnets.
Google's own mitigation is a manual review, which is worth quoting because it is an admission: after new Shared VPC networks or new subnets are added to the host project, a Shared VPC Admin should review the permission bindings for the compute.networkUser role to ensure that the subnet-level permissions for all Service Project Admins match the intended configuration.
#78's mirroring sources include every future instance in a named subnet. #77's organization-level flow logs configuration covers every subnet that comes later. Here, both the sharing scope and the IAM grant extend to networks that do not exist yet. The pattern is the same each time: the convenient option is defined over a set that grows without anyone revisiting the decision, and the only control is a review nobody schedules. Choosing the enumerated form costs more at setup and is the only version that stays true.
Four roles, and the split worth copying
The chain starts above the network. Organization Admins have the resourcemanager.organizationAdmin role for your organization, and they nominate Shared VPC Admins by granting them appropriate project creation and deletion roles , and the Shared VPC Admin role for the organization.
The Shared VPC Admin is the one that actually operates the model: Shared VPC Admins have the Compute Shared VPC Admin ( compute.xpnAdmin ) and Project IAM Admin ( resourcemanager.projectIamAdmin ) roles for the organization or one or more folders. Note that it is two roles, not one — enabling hosts and attaching services needs the XPN role, and delegating subnet access needs the IAM role, because that delegation is itself an IAM binding. Scope inherits downward: a user assigned the Compute Shared VPC Admin role for the organization has that role for all folders in the organization, and a Shared VPC Admin can link projects in two different folders only if the admin has the role for both folders.
Below that, the consumer side: a Shared VPC Admin defines a Service Project Admin by granting an IAM principal the Network User ( compute.networkUser ) role to either the whole host project or select subnets of its Shared VPC networks, and for the work they are actually there to do, they should have the Instance Admin ( compute.instanceAdmin ) role to the corresponding service projects.
Then the split I would copy into any platform design, Shared VPC or not. Network Admins have full control over all network resources except for firewall rules and SSL certificates, because Security Admins manage firewall rules and SSL certificates. Routing and connectivity are one job; filtering and identity material are another. After nine posts on firewall rules it is clear why Google drew the line there — the person who decides where packets can go and the person who decides which packets are allowed are answering different questions, and #80 is about what that division costs in practice.
Why This Architecture Holds Up
Once the model is in place, almost every operational question becomes "which project is this object in?" — and the answers are not uniform.
| Object | Lives in | Note |
|---|---|---|
| Networks, subnets, secondary ranges, firewall rules | Host project | Shared selectively or wholesale with service projects |
| VM instances and their disks | Service project | Created by the Service Project Admin onto a shared subnet |
| Static internal IP address object | Service project | Even though the value of the IP address comes from the available IP addresses of the selected shared subnet |
| Static external IPv4 address object | Either | Defined in the host project can be used by resources in either that host project or any attached service project |
| Load balancer components | Usually the service project | Host-project backends are possible but discouraged |
| Internal DNS name | Names the service project | Point to internal IP addresses in the host project |
| Networks created in a service project | Service project, unshared | Networks defined in service projects are not shared |
Two of those rows are worth dwelling on. The static internal address is the clearest illustration of the whole model: the internal IPv4 or IPv6 address object must be created in the same service project as the resource that uses it, even though the value of the IP address comes from the available IP addresses of the selected shared subnet in a Shared VPC network. The address is a service-project object whose value is drawn from a host-project range — so the API object and the thing it names live in different projects, and a tool that assumes otherwise will look in the wrong place.
The DNS row is the one that will confuse somebody reading a hostname: these DNS names use the project ID of the service project where the VMs are created, even though the names point to internal IP addresses in the host project. So the hostname tells you who owns the workload, not whose network it is on, and in an incident those are exactly the two facts people conflate.
On load balancing the documentation states a preference rather than a rule, and the reasoning is the point: while it's possible to create backend instances in the host project, such a setup is not well suited for typical Shared VPC deployments since it does not separate network administration and service development responsibilities. It is technically allowed and it defeats the purpose, which is a fair summary of most Shared VPC mistakes.
One thing it is important not to over-read: adoption is not compulsory. Use of a Shared VPC network is not mandatory — an instance admin can still create instances in a service project that use a network in that project. So a service project can run a foot in both camps, which is useful during migration and confusing afterwards if nobody writes down which workloads are on which network.
The billing model, and the one path that breaks it
The cost-centre argument is the one most often used to justify Shared VPC, and the general rule supports it. Billing for resources that participate in a Shared VPC network is attributed to the service project where the resource is located, even though the resource uses the Shared VPC network in the host project, at the same rates as if they lived in the host. Egress follows the resource too: outbound traffic from an instance is attributed to the project containing the instance, and costs associated with a load balancer are charged to the project containing the load balancer components. That is why the documentation can offer use service projects to separate budgeting or internal cost centers as a reason to adopt the model at all.
Then the exception, and it is a large one. Outbound traffic to VPNs is attributed to the project containing the VPN Gateway resource — and since the gateway sits in the Shared VPC network, that is the host project. The documentation spells out the consequence: outbound traffic through the VPN Gateway, regardless of which service project initiates the outbound data transfer, is attributed to the host project. Interconnect behaves the same way by a different route: costs for traffic from a resource in a Shared VPC service project that transfers out through a VLAN attachment are attributed to the project that owns the VLAN attachment.
In a hub-and-spoke estate, the hybrid path is often the busiest and most expensive egress there is — backups to on-premises, replication to another cloud, chatty internal services that never moved. All of it bills to the host project, which is typically owned by the platform team and has no visibility into which service project generated it. So the one cost that most needs attributing is the one the model cannot attribute, and the platform team's bill grows for reasons it did not cause. Flow logs are the way back: #77's records carry the reporter and the 5-tuple, and that is the only practical route to splitting hybrid egress by workload. It is also an argument for putting the gateway in a project whose budget somebody owns deliberately.
Limits, and the quota that is not a limit
Three numbers decide how far this scales. Hosts per organization: number of Shared VPC host projects in a single organization 100, raisable through a support case. Hosts per service project: number of host projects to which a service project can attach 1, and this limit can't be increased. And in the other direction, the number of service projects that can be attached to a host project is a configurable per-project quota — so the fan-out is a dial and the fan-in is a wall.
That asymmetry is the whole capacity-planning story. You will never run out of room under a host project in a way that cannot be raised; you can very easily design a workload that needs two host networks and discover there is no supported way to attach it to both. Whether a project will ever need a second network is therefore a question to answer before the first attachment, not after.
Key Architecture Decisions
| Situation | Decision | Because |
|---|---|---|
| Designing the project topology | Flat: host projects as peers, never stacked | A project cannot be both host and service, so there is no nesting. |
| A workload that may need two networks | Decide before the first attachment | One host project per service project, and that limit cannot be raised. |
| Choosing the sharing scope | Enumerate subnets rather than sharing all | Sharing all extends to future subnets and future networks. |
| Granting a Service Project Admin | compute.networkUser on named subnets, not the project |
A project-level grant covers networks added later. |
| Adding a subnet or network to the host | Re-review every networkUser binding |
Google's own stated mitigation for the scope above. |
| Separating network duties | Network Admin and Security Admin as distinct grants | Network Admin excludes firewall rules and SSL certificates by design. |
| Adopting Shared VPC for existing workloads | Plan a rebuild of every instance and private zone | Existing resources cannot be reconfigured onto a shared network. |
| Governing attachment sprawl | Set the constraint, then inventory separately | Both constraints are prospective and leave existing state untouched. |
| Relying on subnet constraints for isolation | Check Private Service Connect separately | PSC endpoint forwarding rules are exempt from the subnet constraint. |
| Attributing hybrid egress to a team | Use flow logs; do not expect the bill to do it | VPN egress bills the gateway's project regardless of the sender. |
| Placing load balancer backends | Service project | Host-project backends are allowed and defeat the separation of duties. |
| Looking for a static internal IP object | Look in the service project | The object is a service-project resource with a host-project value. |
| Reading an internal DNS name during an incident | Read it as the workload's project, not the network's | The name carries the service project ID and resolves into the host's subnet. |
| Attaching across a folder boundary | Expect to need the admin role on both folders | Linking across folders requires rights to both. |
The one to look at today
For each host project, list the compute.networkUser bindings and note which are scoped to the project rather than to named subnets. Every project-level binding is a standing grant over subnets and networks that do not exist yet, which means the blast radius of your next subnet is already decided and nobody will be asked. Then check whether the host project also owns a VPN gateway or a VLAN attachment, because if it does, its budget is carrying hybrid egress generated by service projects that cannot see the charge.
Closing Thought
Shared VPC is the first thing in this block that is purely organisational. There is no data plane behaviour here, no sampling, no packet path — it is a statement about who may change what, expressed in project boundaries and IAM bindings. And it is unusually honest about its own shape: two levels, one host per service project, no nesting, and a long list of things that attaching a project does not do.
What strikes me after nineteen posts is that the recurring failure mode has changed form but not substance. In the observability posts, the trap was reading an estimate as a count. Here it is reading a grant as a boundary. A project-level networkUser binding, a share-all-subnets setting and an organization policy constraint all look like they describe a fixed state, and all three are actually about a moving one — two of them expanding automatically, the third declining to look backwards. The model is sound; what needs watching is that almost every convenient option in it is defined over a set that has not finished growing.
#80 takes the division this post ended on and asks what it costs: Shared VPC IAM and the network admin split — who can actually change a firewall rule when the network belongs to one team and the workload to another.
Comments