Terraform state in a GCS backend: versioning, locking, and per-env separation
Store terraform state in GCS with versioning on the state bucket for recovery. GCS locking is native; separate environments with prefixes or workspaces, never one state file for everything.
Goal: shared, safe terraform state for a team.
Backend config:
terraform {
backend "gcs" {
bucket = "[STATE-BUCKET]"
prefix = "envs/prod"
}
}Setup order:
- Create the state bucket FIRST, outside the terraform that uses it (bootstrap by hand or a separate tiny config). Chicken-and-egg otherwise.
- Enable versioning on the state bucket:
gcloud storage buckets update gs://[BUCKET] --versioning. Corrupted state is recoverable from a prior version. - Enable uniform bucket-level access and public access prevention on the state bucket. State files contain secrets.
- Grant the CI/human identities storage.objectAdmin on the bucket (terraform needs read/write, and locking).
Locking: the GCS backend handles state locking natively. Do not disable it. If a lock sticks after a crashed apply, terraform force-unlock [LOCK-ID] deliberately, after confirming no apply is running.
Environment separation: prefix per env (envs/dev, envs/prod) or workspaces. Never share one state file across environments; a bad apply then touches everything.
Traps:
- State bucket in the SAME terraform config that uses it: the backend needs the bucket before init. Bootstrap separately.
- No versioning: one bad apply corrupts state with no recovery. This is the most expensive terraform mistake on GCP.
- Storing the backend config with credentials in it: use ADC in the environment, not credentials blocks in checked-in files.
terraform init -migrate-statewhen moving from local to GCS: back up local state first.
Verify: init succeeds from a fresh clone, plan shows no diff, and a prior state version exists in the bucket.
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.