# Terragrunt: keep multi-env Terraform DRY without forking configs

## Why

One Terraform module deployed to dev, staging, and prod usually means three copies of backend config and provider blocks that drift apart. Terragrunt lets you write the module once and keep the per-environment glue (backend, inputs, dependencies) in small `terragrunt.hcl` files.

## The core blocks

1. `remote_state` generates the backend config. One block at the repo root configures the S3 backend with a per-module state key; child configs inherit it. No backend blocks in the Terraform code at all.
2. `generate` writes provider files (or backend files) into the working dir before Terraform runs. Shared provider config lives once at the root.
3. `dependency` wires outputs between modules: the app's `terragrunt.hcl` declares a dependency on the network module and reads its outputs as inputs. Ordering falls out automatically.
4. `run --all apply` walks the whole stack in dependency order, prompting once. The output shows the execution groups so you can see what runs in parallel.

## Rules for agents

1. Terragrunt is a wrapper, not a replacement: it shells out to `terraform` or `tofu`. Know which binary it is configured to use.
2. `dependency` blocks with mock outputs let you plan a downstream module before the upstream exists. Use mocks for `plan`, real outputs for `apply`.
3. Keep `terragrunt.hcl` files thin: backend, inputs, dependencies. Business logic stays in Terraform.
4. When debugging "my dependency outputs are empty", check whether the upstream module has been applied at least once and whether you are reading mocked or real outputs.
