Projects, Regions, and Zones
On Google Cloud the project is the fundamental unit of almost everything — billing, quota, IAM, and the boundary nearly every resource lives inside. A bucket, a VM, a dataset: each belongs to exactly one project, and the project carries the billing account those resources draw on, the APIs enabled for them, and the IAM policy that says who can touch them.
Around the project sits the geography. A region like us-central1 is a metro area with multiple zones (us-central1-a, us-central1-b, and so on), and whether a resource is global, regional, or zonal decides its failure domain and how you reference it. An engineer arriving from AWS carries intuitions about VPCs and accounts that are subtly wrong here — untangling them is the point of this topic.
The Project as the Unit
Nearly every resource belongs to exactly one project — organization- and folder-level resources are the exceptions that sit above it, as the IAM chapter covers — and the project is where billing, quota, enabled APIs, and IAM policy all attach. This is the rough analog of an AWS account — but finer-grained and free to create. Where an AWS shop agonizes over how many accounts to run, a GCP org spins up projects freely: one per app, per environment, per team, as isolation demands.
The Hatch org leans on this directly. The serverless pipeline lives in hatch-pipeline-dev; production apps live in hatch-app-prod; a shared network host sits in hatch-net-host. Each is a clean boundary for billing and access, and because projects are cheap, that separation costs nothing but a little wiring. The project id is what every resource and IAM grant keys off.
Regions and Zones
A resource's scope is its failure domain. Zonal resources — a single Compute instance, a zonal persistent disk — live in one zone and vanish if that zone has an outage. Regional resources — a subnet, a regional managed instance group, a Cloud SQL HA instance — span the zones in a region and survive any one zone failing. Global resources — the VPC, Cloud DNS, a global load balancer — span all regions.
This is where AWS intuition misfires hardest. On AWS a VPC is regional; on GCP the VPC is global and only its subnets are regional. An engineer who designs a GCP network expecting per-region VPCs builds the wrong thing. Pick scope deliberately: production workloads with an SLO belong on regional resources, not zonal ones, because a routine zone outage is a when, not an if.
resource "google_compute_instance" "worker" { name = "hatch-worker" zone = "us-central1-a" # zonal — dies with this one zone machine_type = "e2-standard-2" } resource "google_compute_subnetwork" "main" { name = "hatch-main" region = "us-central1" # regional — survives a zone outage network = google_compute_network.main.id ip_cidr_range = "10.0.0.0/20" }
The instance takes a zone and is gone if us-central1-a goes down; the subnet takes a region and rides out any single-zone failure. The google_compute_network they reference takes neither — it is global, spanning every region at once.
Setting Defaults vs Per-Resource
The provider's region and zone are defaults, not mandates. A resource that omits its location inherits them; a resource that needs to live elsewhere overrides them in its own block. So a configuration whose provider defaults to us-central1 can still place one regional resource in europe-west1 by setting region on that resource alone.
Storage breaks the region/zone mold entirely. A Cloud Storage bucket and a BigQuery dataset take a location that may be a single region (us-central1) or a multi-region (US, EU). That is a different axis from the compute region/zone, and the value is fixed at creation — you decide it up front, because changing it later means recreating the resource.
Project Identifiers
A project has three names and they are not interchangeable. The project id (hatch-pipeline-dev) is immutable, globally unique, and the handle everything references. The project number is a numeric identifier some APIs return. The display name is a human label you can rename freely. IAM grants and resource references key off the id — the stable handle, never the mutable display name.
Wiring the wrong identifier in is a quiet bug. Reference a project by display name and the moment someone renames it, the reference breaks; use the number where the id was expected and IAM grants land on nothing. Standardize on the project id everywhere a project is named, and these whole classes of error disappear.
Multi-Region Storage
For storage and BigQuery, multi-region is a durability and latency choice with no compute equivalent. A bucket in the US multi-region or a BigQuery dataset in US stores data redundantly across multiple regions in the United States, surviving a regional failure that a single-region bucket would not. Hatch's hatch-events-raw bucket and its analytics dataset both use the US multi-region for exactly this reason.
The tradeoff is that multi-region is fixed at creation and cannot be narrowed to a single region later without recreating the resource and migrating the data. Decide region versus multi-region up front, based on whether you need cross-regional durability or single-region locality, because the location is a one-time decision baked into the resource.
Global — VPC, Cloud DNS, global load balancers. One resource spans every region at once. This is the scope an AWS engineer least expects, because on AWS the VPC is regional; on GCP it is global and only its subnets are regional.
Regional — subnets, regional managed instance groups, Cloud SQL HA. The resource spans the zones in a region and survives any single zone failing. Choose regional for anything carrying an SLO.
Zonal — a single Compute instance, a zonal disk. The resource lives in one zone with no built-in redundancy and is lost in a zone outage. Fine for scratch and dev work, wrong for production.
- Carrying AWS intuition that a VPC is regional and designing per-region GCP networks — the GCP VPC is global and its subnets are regional, so the design is wrong from the start.
- Putting production on a zonal resource — a single VM or zonal disk — and losing it in a routine zone outage that a regional resource would have ridden out.
- Confusing project id with project number and wiring the wrong one into an IAM grant or a reference, so the grant lands on nothing or the reference fails.
- Referencing a project by its mutable display name, then watching every reference break the moment someone renames the project.
- Choosing a single region for a bucket or dataset when a multi-region was wanted (or the reverse) — the location is fixed at creation and changing it means recreating and migrating data.
- Treat the project as the unit of isolation: one app or environment per project, not one giant shared project, since projects are free to create.
- Choose regional over zonal for anything in production unless you have a stated, written reason to accept a single-zone failure domain.
- Reference projects by their immutable project id everywhere — IAM, resource arguments, backends — never by display name or number.
- Decide region versus multi-region for Cloud Storage and BigQuery up front; the
locationis fixed at creation. - Set provider
regionandzonedefaults, then override per-resource only for the resources that genuinely belong elsewhere.
Knowledge Check
An engineer from AWS designs a GCP network with one VPC per region. Why is that wrong on GCP?
- A GCP VPC is global and spans all regions; only its subnets are regional
- A GCP VPC is a zonal resource and must be created once per zone in the region
- GCP forbids creating more than a single VPC network per project
- Subnets on GCP are themselves global, so a VPC per region is redundant
What is the difference in failure domain between a zonal and a regional resource?
- A zonal resource is lost if its single zone fails; a regional resource spans a region's zones and survives one failing
- A zonal resource spans every region, while a regional resource is pinned to one single zone
- Both ride out a zone outage equally; the only real difference between them is latency
- Neither one survives a zone outage without an operator triggering manual failover, since both scopes pin every replica to the same single physical zone regardless of type
Which project identifier should you wire into IAM grants and resource references?
- The immutable, globally unique project id that stays fixed for the project's life
- The mutable display name, since it is the most human-readable of the identifiers
- The auto-assigned project number, since it is stable and never collides
- Any of the three identifiers — they are fully interchangeable
When does the multi-region versus single-region choice for a bucket actually apply, and what is its catch?
- It applies to storage and BigQuery for cross-regional durability, and the location is fixed at creation
- It applies to Compute Engine instances, and you can change the location any time with a restart
- It applies only to global resources like the VPC, and the location is free to change later
- It applies to every resource type and is purely a cosmetic billing label that groups line items on the invoice without changing where any data physically lives
You got correct