7 Documentation expectations
Good documentation is part of good infrastructure. Terraform code that is not documented is harder to review, harder to maintain, and harder to hand over. This chapter explains what documentation to expect — and how to assess it as a reviewer.
7.1 Why documentation matters more in IaC
In application code, a well-named function often tells you what it does. In Terraform, a well-named resource tells you what it creates, but not necessarily why it is configured the way it is, why it exists in this environment, or what would break if it were removed.
Documentation fills this gap. A reviewer cannot properly assess a Terraform change without understanding its context.
7.2 Variable and output descriptions
Every variable and output should have a description field. This is the minimum standard.
# Good
variable "region" {
description = "The GCP region in which to create resources."
type = string
default = "europe-west2"
}
# Poor — no description, no type
variable "region" {
default = "europe-west2"
}
# Good
output "bucket_name" {
description = "The name of the Cloud Storage bucket used for pipeline outputs."
value = google_storage_bucket.pipeline_outputs.name
}
As a reviewer: If a variable or output has no description, request one. The description should explain what the value is used for, not just repeat the variable name.
7.3 Module README files
Every module in modules/ should have a README.md that explains:
- What the module creates
- What inputs it requires (name, type, description, whether required or optional)
- What outputs it produces
- An example of how to call the module
terraform-docs can generate this automatically from the variable and output descriptions in the code:
terraform-docs markdown table . > README.mdThis is another reason why variable and output descriptions matter — they feed directly into generated documentation.
As a reviewer: If a PR adds or significantly modifies a module, check that the README exists and is up to date. A PR that changes a module’s interface (adds or removes variables, changes output names) must update the README.
7.4 Root module documentation
Root modules (the environment directories like 01_sandbox/) do not always need a full README, but they should have enough context for someone unfamiliar with the project to understand what is being deployed. This can be:
- A
README.mddescribing the purpose of the environment and what it contains - Comments at the top of
main.tfexplaining any non-obvious architectural choices
7.5 Architecture decision records
For significant infrastructure decisions — choosing a particular network topology, deciding to use Cloud SQL rather than Firestore, choosing a specific service account structure — an architecture decision record (ADR) provides a durable record of what was decided and why.
ADRs are stored in the docs/ directory, following the convention established in datasciencecampus/terraform-template.
An ADR does not need to be lengthy. A short document covering:
- Context: What problem were you solving?
- Decision: What did you decide to do?
- Consequences: What are the trade-offs or implications?
is enough to be useful.
As a reviewer: If a PR makes a significant architectural decision without an ADR, you can suggest one — particularly for changes that are hard to reverse or that constrain future options. Not every PR needs an ADR, but reviewers are well placed to spot when one would be valuable.
7.6 Inline comments
Inline comments in Terraform code are appropriate for:
- Explaining why a resource is configured in a non-obvious way
- Noting a known limitation or a follow-up action
- Explaining why a
lifecyclerule orcheckovsuppression is in place
resource "google_storage_bucket" "pipeline_outputs" {
name = "${var.project_id}-pipeline-outputs"
location = var.region
# Uniform bucket-level access is required by our data handling policy.
# Fine-grained ACLs are disabled to prevent accidental per-object permissions.
uniform_bucket_level_access = true
# Prevent accidental deletion of the bucket in non-sandbox environments.
# To delete this bucket, you must first set this to false and apply.
lifecycle {
prevent_destroy = true
}
}
As a reviewer: Comments that explain why (not just what) are valuable. Comments that merely repeat what the code already says are noise. If something in the code is unclear and there is no comment explaining it, ask for one.
7.7 What to check in a review
| Item | Minimum standard | Better standard |
|---|---|---|
| Variables | description set |
description, type, sensible default or no default, and sensitive = true where needed |
| Outputs | description set |
description and sensitive = true where needed |
| Module README | Exists | Generated by terraform-docs, includes example usage |
| Root module | main.tf has a brief header comment |
Full README.md |
| Inline comments | Present for non-obvious choices | Explains why, not just what |
| ADRs | Not required for every PR | Present for significant or hard-to-reverse decisions |