TFNFR39 - Standard File Layout
ID: TFNFR39 - Category: Code Style - Standard File Layout
Every Terraform AVM module (root module and every submodule) MUST organize its top-level Terraform code into the following files at the module’s root directory:
| File | Required | Contents |
|---|---|---|
terraform.tf | MUST | The single terraform { … } block — required_version, required_providers, and any backend configuration (root module only). Provider configuration blocks MUST NOT appear here. |
variables.tf | MUST | All variable blocks for the module. MAY be split into additional variables.<topic>.tf files (see below). |
outputs.tf | MUST | All output blocks for the module. MAY be split into additional outputs.<topic>.tf files (see below). |
main.tf | MUST | The module’s primary resource, data, and module blocks. MAY be split into additional main.<topic>.tf files (see below). |
locals.tf | SHOULD | All locals blocks. Required if the module declares any locals. MAY be split into additional locals.<topic>.tf files (see below). MAY be omitted only when the module has no locals at all. |
Splitting and naming additional files
For larger modules the contents of main.tf, variables.tf, outputs.tf, and locals.tf MAY each be split into multiple files along logical / topic lines. When this is done:
- Additional Terraform files MUST use the canonical filename (
main,variables,outputs, orlocals) as the prefix, followed by a., a short descriptive topic name, and the.tfextension — for examplemain.diagnostic_settings.tf,variables.diagnostic_settings.tf,outputs.diagnostic_settings.tf,locals.diagnostic_settings.tf. - The topic name MUST be
snake_case(per TFNFR3). - The same topic name SHOULD be used across the four file types when they describe the same logical concern, so that (for example)
main.private_endpoints.tf,variables.private_endpoints.tf,outputs.private_endpoints.tf, andlocals.private_endpoints.tfall relate to the same feature. - Each split file MUST contain only the block kind matching its prefix:
main.<topic>.tf— onlyresource,data, andmoduleblocks.variables.<topic>.tf— onlyvariableblocks.outputs.<topic>.tf— onlyoutputblocks.locals.<topic>.tf— onlylocalsblocks.
- The
terraform { … }block MUST appear exactly once per module, interraform.tf. It MUST NOT be split.
Files that MUST NOT appear at the module root
- A
providers.tffile — provider requirements belong interraform.tf; provider configurations belong only in the consumer’s root module, never in an AVM module (per SFR2). - A single monolithic
module.tforeverything.tf— the canonical filenames above MUST be used.
Rationale
Standardizing file layout means that any reviewer or consumer can find a module’s interface (variables.tf, outputs.tf), provider constraints (terraform.tf), and primary logic (main.tf / main.<topic>.tf) in the same place across every AVM Terraform module, without having to grep. It also makes the cascade rules in TFFR6, TFFR7, and TFRMNFR1 reviewable at a glance.
Notes
- Submodules (per TFRMNFR1) follow the same layout in their own root directory under
modules/<subresource>/. The submodule’sterraform.tfMUST declare the same set ofrequired_providersit actually consumes. - Auto-generated documentation files (
README.md,_header.md,_footer.md) and tooling configuration files (.terraform-docs.yml,.tflint.hcl, etc.) are out of scope of this rule and follow their own specs.