DRY remote state
One backend block for the whole repo.
DRY remote state is Terragrunt’s headline win. Instead of a backend block in every unit, you put one remote_state definition in a root terragrunt.hcl and have every child unit include it. Each unit then gets the same backend with a state key derived from its path — so thirty units share one backend definition and each still writes to its own isolated state file. Change the backend once and every unit follows.
remote_state {backend = "s3"generate = { path = "backend.tf", if_exists = "overwrite" }config = {bucket = "acme-tf-state"key = "${path_relative_to_include()}/terraform.tfstate"region = "us-east-1"dynamodb_table = "tf-locks"encrypt = true}}
include "root" {path = find_in_parent_folders("root.hcl") # inherit the backend + more}terraform { source = "git::...//vpc?ref=v1.4.0" }inputs = { cidr_block = "10.20.0.0/16" }
One backend, isolated state per unit
The combination of a shared remote_state and path_relative_to_include() gives you the best of both: one place defines the backend (DRY), and every unit gets a unique state key from its folder structure (isolation). Small isolated states mean a mistake in the app unit cannot corrupt the vpc unit’s state, plans stay fast, and locking is per-unit. This structure is why Terragrunt scales to hundreds of state files sanely.