Where this fits
A Google Cloud landing zone is built in layers — resource hierarchy, identity, networking, security and detective controls, and platform automation — and this article is part 1 because the hierarchy is the substrate everything else attaches to. The resource hierarchy is the tree of organization → folders → projects that all of Google Cloud’s policy machinery hangs off: IAM allow/deny policies inherit down it, the Organization Policy Service applies constraints down it, Shared VPC host projects and the Cloud Asset Inventory scope to nodes in it, and billing rolls up through it. Decide this layer badly and every later design area — your network host projects, your CMEK boundaries, your detective controls in Security Command Center, your Terraform foundation pipeline — inherits the debt and the rework. Decide it well, following the patterns from Google’s Enterprise foundations blueprint and the Cloud Architecture Center landing-zone guidance, and the rest of the build snaps into a tree that is governable, billable, and queryable from day one.

The organization node
What it is
The organization resource (often called the organization node or simply the org) is the single root of the GCP resource hierarchy. It is not something you create with gcloud projects create; it is provisioned automatically the first time a user in your domain creates a Google Cloud resource, and it is tied 1:1 to a Cloud Identity or Google Workspace account. The relationship is strict: a Cloud Identity / Workspace account maps to exactly one organization resource, and that organization is identified by your verified DNS domain (e.g. kloudvin.com) and a numeric organization ID.
Two control planes meet at the org node, and conflating them is the most common day-zero mistake:
- Cloud Identity / Workspace is the identity plane. It owns users, groups, the domain, and one all-powerful role: the Super Admin. The Super Admin verifies domain ownership and performs account recovery — but the Super Admin is not the person who should run the cloud day to day.
- Google Cloud IAM is the resource plane. At org creation, the Super Admin’s first job is to grant the Organization Administrator role (
roles/resourcemanager.organizationAdmin) to a group, and then step back out of routine operations.
Why it matters
The org node is what turns a pile of personal projects into a governed estate. Three properties make it load-bearing:
- Lifecycle ownership. Projects created under an organization belong to the organization, not to the employee who clicked “Create.” When that employee leaves, the project — and its production workload — does not become orphaned or get deleted with their personal account. This single property is the reason “shadow projects” created outside the org are a security and continuity risk.
- Top of the inheritance chain. Any IAM policy or organization-policy constraint set at the org node flows to every folder, project, and resource beneath it and cannot be revoked lower down (a child can add restriction, never remove a parent’s deny). This is exactly why you place your non-negotiable, estate-wide guardrails here and nowhere else.
- Single pane. Cloud Asset Inventory, Security Command Center, BigQuery billing export, and Access Context Manager all scope cleanly to the org node, giving you one place to query “everything we run.”
How to do it well
- Provision Cloud Identity first, deliberately. Verify the domain, decide federation with your IdP (Entra ID, Okta, Ping) before any project exists, so users are real federated identities — never
@gmail.comconsumer accounts — from the first login. - Get the Super Admin out of IAM. Treat Super Admin accounts as break-glass: hardware-key MFA, ideally 2+ accounts for recovery, used only for identity emergencies. Grant
organizationAdminto a dedicated group (gcp-org-admins@) and operate from there. - Keep the org node almost empty of IAM. Bind only a tiny set of roles at the very top —
organizationAdmin,orgpolicy.policyAdmin, billing and security viewers for central teams. Everything else belongs on folders and projects. - Set a default org-policy baseline immediately, before teams arrive (see the table below). Retro-fitting deny constraints onto a populated org is painful.
Concrete artifacts, decisions, and tools
| Artifact / decision | GCP service or tool | Notes |
|---|---|---|
| Verified domain + users/groups | Cloud Identity (or Google Workspace) | 1:1 with the org node; federate to your corporate IdP via SAML/OIDC |
| Organization Administrator group | Cloud IAM (roles/resourcemanager.organizationAdmin) |
Granted by Super Admin once, then Super Admin steps away |
| Estate-wide guardrails | Organization Policy Service (gcloud org-policies) |
e.g. iam.disableServiceAccountKeyCreation, compute.requireOsLogin, gcp.resourceLocations, iam.allowedPolicyMemberDomains, sql.restrictPublicIp |
| Where new projects may attach | constraints/resourcemanager.allowedResourceCreationLocations style controls + IaC |
Force projects to be created under governed folders, not loose under org |
| Org-wide inventory & search | Cloud Asset Inventory | Feeds drift detection and the Terraform foundation |
| Inheritance documentation | Architecture decision record (ADR) | Records org ID, Super Admin custody, admin group, baseline constraints |
A representative day-zero org-policy baseline:
| Constraint | Effect | Why at the org node |
|---|---|---|
iam.allowedPolicyMemberDomains |
Only your Cloud Identity customer ID may receive IAM grants | Blocks accidental access to external/consumer accounts estate-wide |
iam.disableServiceAccountKeyCreation |
No downloadable SA keys | Forces Workload Identity Federation / short-lived creds everywhere |
gcp.resourceLocations |
Restrict to approved regions (e.g. in:eu-locations, asia-south1) |
Data-residency / sovereignty as a hard floor |
compute.requireOsLogin |
SSH via IAM + OS Login only | Removes per-VM key sprawl |
compute.vmExternalIpAccess |
Deny external IPs by default | Private-by-default posture inherited downward |
sql.restrictPublicIp / storage.publicAccessPrevention |
No public Cloud SQL / public buckets | High-blast-radius footguns closed before teams arrive |
Folders by environment and team
What it is
A folder is the optional grouping node that sits between the organization and projects. Folders can contain projects and other folders, and they are the natural attachment point for IAM allow policies and organization-policy constraints that should apply to a set of projects but not the whole estate. The hard structural limits matter for design:
- Up to 10 levels of folder nesting beneath the organization node.
- Up to 300 child folders under any single parent.
Those numbers are generous, but good hierarchies use almost none of that depth. Two to four meaningful levels is plenty for most enterprises; every extra level multiplies the “which policy wins here?” cognitive load and the surface area for misconfiguration.
The blueprint convention is that folders express two orthogonal axes: environment (production / non-production / development / sandbox) and team or business unit (a product team, a domain, a subsidiary). The whole design question — covered in the trade-offs section below — is which axis you put on top.
Why it matters
Folders are where delegated administration and environment isolation actually happen:
- Environment folders let you apply strict production guardrails (no public IPs, mandatory CMEK, change-controlled IAM) to the
productionsubtree while keeping adevelopmentsubtree loose enough for engineers to move fast. Because organization policies inherit, a single constraint on theproductionfolder protects every current and future project under it. - Team folders let you grant a product team’s group
roles/resourcemanager.folderAdmin(or scoped roles) on their folder, so they self-serve project creation and IAM within a fenced blast radius — without ever touching another team’s resources or the org node. - Cost attribution rolls up the folder tree: Cloud Billing reports and the BigQuery billing export let you aggregate spend by folder, so an environment folder or a team folder becomes a natural cost center even though billing is technically assigned per project.
How to do it well
- Carve out platform folders directly under the org, separate from workloads. The Enterprise foundations blueprint puts a
bootstrapfolder right below the org node (it holds the seed/CI-CD projects that build the rest of the foundation via IaC — the chicken that lays every other egg) and acommonfolder for shared services (centralized logging, org-wide security tooling, shared VPC/DNS) that span environments. Keeping these out of the environment/team subtree means the tooling that governs the estate is not itself governed by application guardrails. - Group by guardrail similarity, not the org chart. Folders are a governance tree, not an HR tree. If two teams need identical policy, they can share a folder; if Marketing reorganizes, your folder tree should not have to migrate.
- Stay shallow and consistent. Pick one pattern (next section) and apply it uniformly. Mixing “environment-on-top” in one branch and “team-on-top” in another is how estates become un-navigable.
- Standardize folder naming. A predictable scheme (
fldr-prod,fldr-nonprod,fldr-<team>-prod) makes IaC, asset queries, and audits trivial.
Concrete artifacts, decisions, and tools
| Artifact / decision | GCP service or tool | Notes |
|---|---|---|
| Folder tree itself | Resource Manager (gcloud resource-manager folders create) or Terraform google_folder |
Built and version-controlled by the foundation pipeline |
| Per-folder guardrails | Organization Policy Service attached at folder scope | e.g. deny external IPs on production, allow on a sandbox folder |
| Delegated team access | Cloud IAM roles on folders (folderAdmin, folderIAMAdmin, custom roles) |
Granted to Google Groups, never to individuals |
| Bootstrap / seed | bootstrap folder + seed project + Terraform service account |
Houses the CI/CD that provisions everything else (terraform-example-foundation pattern) |
| Shared services | common folder |
Centralized logging sink project, SCC project, interconnect/DNS host projects |
| Cost rollups | Cloud Billing reports + BigQuery billing export | Aggregate by folder for environment/team cost centers |
Projects
What it is
A project is the base-level node of the hierarchy and the fundamental organizing entity of Google Cloud — every resource (a Compute Engine VM, a Cloud Storage bucket, a BigQuery dataset, a GKE cluster) lives in exactly one project. A project is also the unit at which you enable APIs, attach a billing account, set quotas, and bound an IAM trust domain. A project carries three identifiers, and the distinction is operationally important:
| Identifier | Mutable? | Used for |
|---|---|---|
| Project ID | Set once at creation, immutable | The globally-unique, human-chosen handle in CLI/API/URLs (e.g. kv-shop-prod-9f3a) |
| Project number | Auto-generated, immutable | Read-only numeric ID some APIs and IAM principalSet:// bindings reference |
| Display name | Mutable | The friendly label in the console; can change freely |
Because the project ID is immutable and globally unique, your naming convention is a one-shot decision — you cannot rename it later, only create a new project and migrate.
Why it matters
The project is the primary unit of isolation, billing, and quota in GCP — the rough analogue of an AWS account or an Azure subscription, but far cheaper to create, so you can afford many of them:
- Blast-radius boundary. Compromise or misconfiguration in one project is fenced from others. A per-app, per-environment project (
shop-prod,shop-nonprod,shop-dev) means a bad IAM grant in dev cannot touch prod data. - Billing & quota boundary. Each project attaches to one billing account and carries its own API quotas; this is how you stop a runaway batch job in one team from exhausting another’s Compute quota.
- IAM boundary. A project is a clean trust domain — service accounts, Workload Identity, and per-resource IAM all resolve within it.
The design tension is granularity: too few projects and you lose isolation and clear cost attribution; too many and you drown in management overhead (hence you automate project creation via a project factory).
How to do it well
- One workload, one environment, one project. The widely-used default is a project per (application × environment) —
app-dev,app-nonprod,app-prod— placed under the right environment/team folder. This gives clean isolation and per-environment cost lines. - Automate creation with a project factory. Never click-create production projects. Use the
project-factoryTerraform module (part of the Cloud Foundation Toolkit) so every project lands with: the correct parent folder, a billing account, labels, baseline APIs, a default network policy, and break-glass IAM — consistently. - Label everything. Apply labels (
env,team,cost-center,data-classification,app) at creation. Labels are how billing export, asset queries, and FinOps reporting slice the estate; they are not optional metadata. - Use Shared VPC service projects. Application projects should be service projects that attach to a central Shared VPC host project (defined in your networking layer, part 3 of this series) rather than each running its own VPC.
- Reserve a quarantine/CICD path. New projects should be created into a governed folder by the factory, never loosely under the org node where no environment policy applies.
Concrete artifacts, decisions, and tools
| Artifact / decision | GCP service or tool | Notes |
|---|---|---|
| Project creation at scale | terraform-google-modules/project-factory (CFT) |
Enforces folder, billing, labels, APIs, default deny network |
| Immutable ID scheme | Naming standard, e.g. kv-<app>-<env>-<rand> |
One-shot; lock it down before scale-out |
| Labels taxonomy | Resource labels | env, team, cost-center, data-classification, app |
| Billing linkage | Cloud Billing account attach | One billing account, attributed per project |
| Service-project attachment | Shared VPC (gcloud compute shared-vpc associated-projects add) |
App projects consume central network |
| Quota & API enablement | Service Usage API | Baseline APIs enabled by the factory |
Resource-hierarchy design patterns and trade-offs
What it is
Google’s landing-zone guidance names three canonical hierarchy patterns, distinguished by what you put on the top folder axis. All three keep bootstrap and common folders directly under the org node; they differ only in how the workload subtree is organized.
Pattern A — Environment-oriented (top axis = environment)
Organization (kloudvin.com)
├── bootstrap (seed + CI/CD, IaC)
├── common (logging, security, shared VPC/DNS)
├── production
│ ├── shop-prod (project)
│ └── payments-prod (project)
├── non-production
│ ├── shop-nonprod
│ └── payments-nonprod
└── development
├── shop-dev
└── payments-dev
Pattern B — Team / business-unit-oriented (top axis = team)
Organization
├── bootstrap
├── common
├── retail-team
│ ├── prod / nonprod / dev (projects or sub-folders)
├── payments-team
│ ├── prod / nonprod / dev
└── data-platform-team
└── prod / nonprod / dev
Pattern C — Hybrid (recommended for most: environment on top, teams beneath)
Organization
├── bootstrap
├── common
├── production
│ ├── retail-team → shop-prod
│ └── payments-team → payments-prod
├── non-production
│ ├── retail-team → shop-nonprod
│ └── payments-team → payments-nonprod
└── development
├── retail-team → shop-dev
└── payments-team → payments-dev
A fourth real-world variant — region / subsidiary / legal-entity-oriented — puts a top axis like apac, emea, india-entity first, and is used when data sovereignty or legal separation dominates every other concern.
Why it matters
The pattern choice is hard to reverse: moving projects between folders is possible but re-parents all inherited IAM and org policy, so you want to choose deliberately. It is fundamentally a trade-off between policy simplicity, team autonomy, and cost/ownership clarity.
| Pattern | Top axis | Policy/guardrail simplicity | Team autonomy & delegation | Cost & ownership clarity | Best when |
|---|---|---|---|---|---|
| A — Environment | prod / nonprod / dev | Strongest — one prod policy set covers all apps; easy to lock prod hard | Weaker — a team’s resources are split across env folders, harder to delegate one folder | Cost is naturally per-environment; per-team needs labels | Strict, uniform compliance posture; few teams; environment policy dominates |
| B — Team / BU | per team | Weaker — every team folder needs its own prod-grade constraints; risk of drift | Strongest — delegate one folder per team, full self-service blast-radius | Strongest — folder = cost center = owner | Many autonomous product teams; strong FinOps-by-team need |
| C — Hybrid (env→team) | env, then team | Strong — prod guardrails on env folder, inherited by all teams’ prod | Strong — team sub-folders under each env are delegable | Good — slice by env and team via folders + labels | Most enterprises — balances all three; the foundations-blueprint default |
| D — Region / entity | region / legal entity | Strong for residency (gcp.resourceLocations per region folder) |
Per-entity delegation | Per-entity billing accounts often required | Sovereignty / legal separation is the overriding driver |
How to do it well
- Default to the hybrid pattern © unless a specific force overrides it. Environment-on-top gives you clean, inheritable prod guardrails; team sub-folders give you delegation and team cost rollups. It is what the Enterprise foundations blueprint and most large GCP estates land on.
- Let the dominant constraint pick the top axis. If uniform compliance is non-negotiable → environment on top (A/C). If autonomous teams and per-team P&L dominate → team on top (B). If data residency / legal entities dominate → region/entity on top (D).
- Keep
bootstrapandcommonout of the workload axis in every pattern, directly under the org, so foundation tooling and shared services aren’t subject to application guardrails. - Cover what folders can’t with labels. Whichever axis you don’t put in folders (team in pattern A, environment in pattern B) you recover through mandatory labels + BigQuery billing export — so you can always slice cost by both env and team.
- Stay shallow. Even with 10 levels available, prefer ≤4. Encode the rest (app, region) in project IDs and labels, not in ever-deeper folders.
Real-world enterprise scenario
KloudVin Retail Group is a fictional ₹4,200-crore omnichannel retailer (≈US$500M revenue) with ~900 engineers across three product domains — Storefront (e-commerce web/app), Payments & Wallet (PCI-DSS scope), and Data & ML (recommendations, demand forecasting). They are mid-migration from on-prem and a sprawl of ungoverned GCP projects that individual teams created with personal accounts. The mandate: a governed landing zone, data residency in asia-south1 (Mumbai) and asia-south2 (Delhi), PCI isolation for Payments, and per-team cost accountability for FinOps. Budget discipline is real — this is INR, and runaway dev spend has burned them before.
Organization node. They verify kloudvinretail.com in Cloud Identity, federate to their existing Entra ID via SAML so all 900 engineers log in with corporate identities (no consumer accounts). The Workspace Super Admin is split across two hardware-key break-glass accounts held by the cloud lead and the CISO, used only for identity recovery. The Super Admin grants roles/resourcemanager.organizationAdmin to gcp-org-admins@kloudvinretail.com (5 platform engineers) and exits routine ops. Day-zero org-policy baseline: gcp.resourceLocations = in:asia-south1, asia-south2 (hard residency floor), iam.disableServiceAccountKeyCreation, iam.allowedPolicyMemberDomains locked to their customer ID, compute.vmExternalIpAccess denied, storage.publicAccessPrevention enforced.
Folders. They adopt the hybrid pattern ©. Directly under the org: a bootstrap folder (seed project + the Terraform foundation CI/CD running in Cloud Build) and a common folder (centralized log sink project, a Security Command Center Premium project, and the Shared VPC host projects for each environment). The workload subtree is environment-first:
Organization (kloudvinretail.com)
├── bootstrap → prj-bootstrap-seed, prj-cicd
├── common → prj-logging, prj-scc, prj-net-hub-{prod,nonprod}
├── production
│ ├── storefront → prj-store-prod
│ ├── payments → prj-pay-prod (PCI subtree, tightest policy)
│ └── data-ml → prj-data-prod
├── non-production
│ ├── storefront / payments / data-ml
└── development
├── storefront / payments / data-ml
The production folder carries the strict guardrails (deny external IP — already inherited, mandatory CMEK via constraints/gcp.restrictNonCmekServices, change-controlled IAM); the payments sub-folders under prod and nonprod get additional PCI constraints (restricted egress, VPC-SC perimeter membership). The development folder relaxes a few constraints and — crucially for budget — carries per-project budget alerts so a forgotten GPU notebook pages the team before it pages finance. Each product domain’s group gets roles/resourcemanager.folderAdmin on their sub-folders within each environment, so Storefront self-serves its own dev/nonprod projects but cannot touch Payments.
Projects. Created exclusively by the project-factory Terraform module — never by hand. Naming is the immutable scheme kvr-<domain>-<env>-<rand> (e.g. kvr-store-prod-7b21). Every project lands with labels env, team, cost-center, data-classification, attaches to one billing account, enables only baseline APIs, and is wired as a Shared VPC service project to the matching common host project. The factory produces ~70 projects across the three domains × three environments × a handful of apps.
Artifacts produced. A Cloud Identity tenant with Entra federation; an org-policy baseline as Terraform (google_org_policy_policy); the bootstrap/common/env/team folder tree as google_folder resources; a project-factory module instantiated per app; a labels taxonomy doc; a BigQuery billing export with Looker Studio dashboards sliced by env and team; and an ADR recording org ID, Super Admin custody, and pattern choice.
Measurable outcome (6 months): shadow/ungoverned projects went from ~140 to 0 (all migrated under the org or decommissioned); 100% of projects carry the four mandatory labels (enforced by IaC validation in the pipeline), versus ~30% before; FinOps can now attribute 100% of spend to a team and environment, and dev-environment budget alerts cut idle dev spend by ~38%; PCI auditors accepted the payments folder + VPC-SC perimeter as the documented cardholder-data boundary, shortening the assessment.
Deliverables & checklist
Common pitfalls
- Running everything as Super Admin / Organization Admin. The Workspace Super Admin and
organizationAdminare estate-god roles. Using them for daily work means one phished session compromises the whole org. Avoid: Super Admin = break-glass only (hardware keys, ≥2 accounts); operate from scoped groups on folders/projects, never from the org node. - Mirroring the org chart in folders. Building the folder tree to match departments means every reorg triggers a re-parenting migration that resets inherited IAM and org policy. Avoid: group by guardrail similarity and environment; recover the org-chart view through labels, not folder structure.
- Going too deep. Just because you can nest 10 levels doesn’t mean you should. Deep trees make “which policy wins here?” unanswerable and slow audits. Avoid: ≤4 meaningful levels; push app/region detail into project IDs and labels.
- Hand-creating projects. Click-created projects land with no parent folder, no labels, default-open networking, and inconsistent IAM — the exact shadow-project problem you set out to kill. Avoid: the
project-factorymodule is the only sanctioned path; deny loose creation under the org with policy. - Treating the project ID as renameable. Teams pick a throwaway ID, scale to 70 projects, then discover the ID is immutable and globally unique and baked into IAM bindings and URLs. Avoid: lock the naming scheme before scale-out; use the mutable display name for cosmetic labels.
- Forgetting
bootstrap/commonbelong outside the workload axis. Putting the CI/CD seed project or the central log sink insideproductionsubjects your governance tooling to application guardrails (and risks a circular dependency where the thing that builds the foundation is blocked by the foundation’s own policy). Avoid: keepbootstrapandcommondirectly under the org node.
What’s next
Part 2 of Google Cloud Landing Zone Design moves up the stack to Identity & Access — designing Cloud Identity federation, the IAM allow/deny model, Google Groups for delegated administration, and Workload Identity Federation across the hierarchy you just built.