Resource Hierarchy and Projects
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. See the section bibliography for the reference material consulted while preparing these pages. |
Commands and console steps below were checked against the gcloud CLI reference and the Resource Manager, Organization Policy and Cloud Quotas documentation on 2026-10-01; re-verify against the linked reference pages if you are reading this later. The project is the basic container for resources, APIs, IAM bindings, quotas and billing in Google Cloud. Projects can be grouped into folders under an organization, and policies attached to those levels flow downward. This page covers that hierarchy, the three project identifiers, labels and tags, the Organization Policy Service with the secure-by-default constraints, quotas, the billing-account link, and the project layout of the Bookshelf scenario. Signing up and creating the very first project are in Getting Started with Google Cloud; who may do what inside the hierarchy is in Identity and Access.
The hierarchy
Google Cloud resources form a tree with four kinds of node:
- Organization
-
The root node, tied to a Cloud Identity or Google Workspace domain. It exists only when your company has such a domain; an individual with a personal Google account has projects but no organization. It has a numeric organization ID.
- Folders
-
Optional containers for projects and other folders, used to mirror teams, business units or environments. Folders nest (up to ten levels deep) and have a numeric folder ID.
- Projects
-
The required container for service resources such as a Cloud Run service, a Cloud Storage bucket or a Compute Engine VM. Every resource belongs to exactly one project.
- Resources
-
The leaf nodes: buckets, VMs, databases, secrets and so on.
IAM allow policies and organization policies attached to a node are inherited by everything below it, so a role granted on a folder applies to every project in it. Inheritance is additive for IAM (a child can grant more, never revoke what the parent granted, except through deny policies) while organization policies can be merged or overridden according to the constraint. Billing is separate from the tree: a project is linked to a billing account, which is its own resource and can be shared by projects anywhere in the hierarchy. The Azure and AWS counterparts are management groups and subscriptions (Resource Organization) and organizational units and accounts (Accounts and Organizations).
The diagram shows the layout used by Bookshelf. The names and numbers are placeholders.
example.com (123456789012)"] --> FSH["Folder: shared"] ORG --> FBK["Folder: bookshelf"] ORG --> FSB["Folder: sandbox"] FSH --> PNET["Project: example-net-prod"] FSH --> PLOG["Project: example-logging"] FBK --> PDEV["Project: bookshelf-dev"] FBK --> PSTG["Project: bookshelf-stg"] FBK --> PPRD["Project: bookshelf-prod"] FSB --> PSBX["Project: sandbox-alice"] PPRD --> RES["Resources: Cloud Run, Cloud SQL,
Cloud Storage, Secret Manager"] POL["IAM policies and organization policies
inherited downward"] -.-> FBK BA["Billing account"] -.-> PDEV BA -.-> PSTG BA -.-> PPRD
Projects
Name, ID and number
Every project has three identifiers, and mixing them up is a common source of errors:
- Project name
-
A human-friendly display name, 4 to 30 characters, not unique and changeable at any time.
- Project ID
-
A globally unique string chosen at creation, 6 to 30 characters of lowercase letters, digits and hyphens, starting with a letter and not ending with a hyphen. It is immutable, it is what
--projectand most APIs expect, and it appears in resource names such asgcr.iopaths and default service-account emails, so choose it deliberately. Avoid putting sensitive information in it. Words such asgoogleandsslare not allowed. - Project number
-
A numeric identifier assigned by Google Cloud, unique and immutable. It appears in the default service-account emails (
PROJECT_NUMBER-compute@developer.gserviceaccount.com), in Workload Identity Federation principals and in some resource names.
Project IDs are never reusable once the project is deleted, so even a throwaway experiment permanently consumes its ID.
One project per application per stage
A project is a strong boundary for IAM, quota, API enablement, audit logs and cost reporting, which suggests the
usual layout: one project per application per life-cycle stage, grouped in a folder per application or team.
Bookshelf therefore uses bookshelf-dev, bookshelf-stg and bookshelf-prod inside a bookshelf folder, with
shared networking and logging in a shared folder. Benefits:
-
Production data and credentials are unreachable from development roles by default.
-
Quotas are per project, so a load test in staging cannot exhaust production’s limits.
-
Costs are attributed per project without extra labelling.
-
Service accounts and enabled APIs differ per stage, which keeps least privilege practical.
Older beginner guides put everything in a single project, which is fine for learning but not for anything a team shares. The resource-hierarchy best practice is to design folders around your governance needs, not your org chart, and to keep the number of levels small.
In the Google Cloud console
-
Open the project picker in the top bar and choose New project.
-
Enter the Project name; the console proposes a Project ID that you can edit (it cannot be changed later).
-
Under Billing account pick the billing account to link, and under Location choose the organization or folder that will contain the project.
-
Choose Create and wait for the notification, then select the project in the picker.
-
To move a project, open IAM & Admin, then Manage resources, select the project, choose Move and pick the destination folder. To delete it, select it and choose Delete; to see deleted projects use Resources pending deletion.
With the gcloud CLI
gcloud services enable cloudresourcemanager.googleapis.com cloudbilling.googleapis.com
ORG_ID=123456789012 # placeholder; see "gcloud organizations list"
PROJECT_ID=bookshelf-dev-example
# Organizations visible to you, and folders directly under one
gcloud organizations list
gcloud resource-manager folders create --display-name=bookshelf --organization="$ORG_ID"
FOLDER_ID=$(gcloud resource-manager folders list --organization="$ORG_ID" \
--filter="displayName=bookshelf" --format="value(name.basename())")
# Create a project inside the folder, then inspect it
gcloud projects create "$PROJECT_ID" --name="Bookshelf Dev" --folder="$FOLDER_ID"
gcloud projects describe "$PROJECT_ID" \
--format="value(projectId,projectNumber,parent.id)"
gcloud projects list --filter="parent.id=$FOLDER_ID" --format="table(projectId,name,projectNumber)"
# Make it the default project of the active gcloud configuration
gcloud config set project "$PROJECT_ID"
# Move it to another folder later
gcloud projects move "$PROJECT_ID" --folder="$OTHER_FOLDER_ID"
Reference: https://docs.cloud.google.com/sdk/gcloud/reference/projects/create, https://docs.cloud.google.com/sdk/gcloud/reference/resource-manager/folders/create and https://docs.cloud.google.com/resource-manager/docs/creating-managing-projects
Creating a project needs the resourcemanager.projects.create permission, usually granted with the Project
Creator role (roles/resourcemanager.projectCreator) on the organization or folder. Creating folders needs the
Folder Creator role (roles/resourcemanager.folderCreator). Deleting a project does not free its resources
instantly: it enters a soft-deleted state for 30 days, during which it can be restored with
gcloud projects undelete, still counts against your project quota, and is then removed permanently.
Linking a billing account
A project can create billable resources only while it is linked to an open billing account. Linking needs the
Billing Account User role (roles/billing.user) on the billing account and the permission to modify the project’s
billing, normally Project Billing Manager. Budgets, cost exports and spending reports are covered in
Cost Management and Billing.
In the Google Cloud console
-
Open Billing, choose Account management and note the billing account that should pay.
-
In the same page choose Link a project (or open Billing from the target project) and select the project.
-
Confirm; the project’s Billing page now shows the linked account. To unlink, use Disable billing there, which stops the project’s billable resources.
Labels and tags
Google Cloud has two different annotation mechanisms, and they serve different purposes.
- Labels
-
Key-value pairs attached to a resource (such as a project, a VM or a bucket) that are used for filtering, grouping and, above all, cost attribution: labels appear in billing exports and reports. They are not used to make access or policy decisions. A resource can carry up to 64 labels; keys and values are lowercase letters, digits, underscores and hyphens.
- Tags
-
Resource Manager resources defined at the organization or project level as a tag key with tag values, then bound to organizations, folders, projects or other supported resources. Tags are inherited down the hierarchy and can be used in IAM conditions, in organization policy rules and in firewall policies, so they control behaviour rather than just describe it. Tag keys and values have IDs and need the Tag Administrator role to manage.
As a rule of thumb: label for reporting, tag for governance. Network tags on Compute Engine VMs are a third, older and unrelated concept.
In the Google Cloud console
-
For labels, open IAM & Admin, then Labels, select the project, add key-value pairs and choose Save.
-
For tags, open IAM & Admin, then Tags, choose Create tag, give it a short name such as
environment, add values such asproductionanddevelopment, and save. -
Open Manage resources, select a project or folder, and use the Tags tab to bind a tag value to it.
With the gcloud CLI
# Labels (cost attribution)
gcloud projects update "$PROJECT_ID" --update-labels=app=bookshelf,stage=dev
gcloud projects describe "$PROJECT_ID" --format="value(labels)"
# Tags (governance): create a key and a value, then bind the value to a project
gcloud resource-manager tags keys create environment --parent="organizations/$ORG_ID"
gcloud resource-manager tags values create production \
--parent="$ORG_ID/environment"
PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" --format="value(projectNumber)")
gcloud resource-manager tags bindings create \
--tag-value="$ORG_ID/environment/production" \
--parent="//cloudresourcemanager.googleapis.com/projects/$PROJECT_NUMBER"
Organization policies
The Organization Policy Service lets an administrator set guardrails on what resources may be configured, for example "no external IPs on VMs" or "only these regions". It is different from IAM: IAM decides who can act, an organization policy decides what configurations are allowed whatever the caller’s permissions.
-
A constraint is a named restriction such as
constraints/gcp.resourceLocations. Constraints are either boolean (enforced or not) or list (allowed or denied values), and are provided by Google or defined as custom constraints. -
A policy sets a constraint on a node of the hierarchy. Child nodes inherit it; a policy can merge with the parent or replace it, and a policy can use tags in a condition to apply only to some resources.
-
The Organization Policy Administrator role (
roles/orgpolicy.policyAdmin) is required to set policies. -
Dry-run mode logs what would be blocked before you enforce, and is the safe way to roll out a new guardrail.
Secure-by-default constraints
Organizations created on or after 2024-05-03 (and some created between February and April 2024) are created with a baseline of enforced policies. Older guides, including the many that start with downloading a service-account key, assume none of these exist and fail in such organizations:
| Constraint | Effect |
|---|---|
|
Persistent service-account keys cannot be created. |
|
External public keys cannot be uploaded to service accounts. |
|
Default service accounts no longer receive the broad Editor role automatically. |
|
IAM bindings are limited to identities from your own domains. |
|
Essential Contacts must belong to managed domains. |
|
Protocol forwarding is limited to internal addresses. |
|
New buckets use uniform bucket-level access, so per-object ACLs are rejected. |
The practical consequences for Bookshelf: workloads authenticate with attached service accounts and Workload Identity Federation instead of keys (see Identity and Access), and the application service account must be granted its roles explicitly. An administrator can relax a constraint for a folder or project when there is a justified exception, but it is better to change the design than the policy.
In the Google Cloud console
-
Select the organization, folder or project in the resource picker.
-
Open IAM & Admin, then Organization Policies.
-
Search for a constraint (for example Define allowed Google Cloud locations) and open it to see its current and effective policy.
-
Choose Manage policy, set the enforcement or the allowed values, and choose Set policy. Use Test changes or the dry-run option first.
With the gcloud CLI
gcloud services enable orgpolicy.googleapis.com
# Inspect what applies to a project, including inherited policies
gcloud org-policies list --project="$PROJECT_ID"
gcloud org-policies describe iam.managed.disableServiceAccountKeyCreation \
--project="$PROJECT_ID" --effective
# Restrict resource locations for the bookshelf folder
cat > location-policy.yaml <<'YAML'
name: folders/FOLDER_ID/policies/gcp.resourceLocations
spec:
rules:
- values:
allowedValues:
- in:europe-locations
YAML
sed -i.bak "s/FOLDER_ID/$FOLDER_ID/" location-policy.yaml
gcloud org-policies set-policy location-policy.yaml
# Remove a policy set at a node so the parent's applies again
gcloud org-policies delete gcp.resourceLocations --folder="$FOLDER_ID"
Reference: https://docs.cloud.google.com/sdk/gcloud/reference/org-policies, https://docs.cloud.google.com/resource-manager/docs/organization-policy/creating-managing-policies and https://docs.cloud.google.com/resource-manager/docs/secure-by-default-organizations
The older gcloud resource-manager org-policies command group still exists but the gcloud org-policies group,
which targets the Organization Policy v2 API, is the current one.
Quotas and limits
Quotas cap how much of a resource a project can use, to protect you from runaway cost and Google from abuse. There are rate quotas (requests per minute), allocation quotas (number of resources, such as CPUs per region) and fixed system limits that cannot be raised. Quotas are per project, which is one more reason to separate stages. The Cloud Quotas service lets you see usage, set quota preferences and request an increase, which Google reviews and may grant automatically.
In the Google Cloud console
-
Open IAM & Admin, then Quotas & System Limits.
-
Filter by service (for example Cloud Run Admin API) or by name, and sort by Current usage percentage.
-
Select a quota, choose Edit quota, enter the new value with a justification, and submit the request.
Cost and limits of this page’s features
Resource Manager, projects, folders, labels, tags, the Organization Policy Service and Cloud Quotas have no charge of their own; you pay for the resources inside the projects and, where applicable, for support. There is no free-tier concept here, but an account has a default limit on the number of projects it may create (raised through the quota request form), and soft-deleted projects count against it for 30 days. Current pricing for the services you place in projects is on https://cloud.google.com/pricing and each product’s pricing page.
Clean up
Remove things in dependency order, working from the leaves up:
-
Delete or move the resources inside each project (see the clean-up section of the page for each service).
-
Remove tag bindings and tag values before the tag key:
gcloud resource-manager tags bindings delete \ --tag-value="$ORG_ID/environment/production" \ --parent="//cloudresourcemanager.googleapis.com/projects/$PROJECT_NUMBER" gcloud resource-manager tags values delete "$ORG_ID/environment/production" gcloud resource-manager tags keys delete "$ORG_ID/environment" -
Delete organization policies you set for the experiment:
gcloud org-policies delete gcp.resourceLocations --folder="$FOLDER_ID" -
Delete the throwaway project; this schedules the whole project, with everything in it, for permanent removal after 30 days. Restore it before then with
gcloud projects undelete. Some resources have their own retention after the project is gone, such as Cloud Storage soft-delete, Secret Manager versions and Cloud SQL retained backups, which are covered on their pages.gcloud projects delete "$PROJECT_ID" gcloud projects undelete "$PROJECT_ID" # only if you change your mind within 30 days -
Delete the now-empty folder:
gcloud resource-manager folders delete "$FOLDER_ID" -
Unlink or close billing accounts only if they were created for the experiment; a billing account cannot be deleted, only closed, from Billing then Account management.