TF

Terraform Module Patterns

Module composition, structure, and reusability patterns

Details

Language / Topic
terraformTerraform
Category
Architecture

Rules

balanced
- Create modules for reusable infrastructure patterns — a module should encapsulate one logical component
- Use a standard module structure: main.tf, variables.tf, outputs.tf, README.md, examples/
- Pin module versions in source references: source = "git::https://...?ref=v1.2.0"
- Expose configuration through variables with sensible defaults; avoid modules that require 20+ required variables
- Keep modules small and composable — prefer composition over monolithic modules
- Create modules for patterns used more than once — a module encapsulates one logical component (e.g., "vpc", "lambda-api")
- Standard module structure: main.tf, variables.tf, outputs.tf, versions.tf, README.md, examples/, tests/
- Pin module source versions: ?ref=v1.2.0 for git, version = "~> 3.0" for registry modules
- Design module interfaces with sensible defaults: minimize required variables, use optional() for complex objects
- Keep modules small and composable: a VPC module + a security group module, not one mega-networking module
- Use output values to expose resource attributes other modules need; output resource IDs, ARNs, and names
- Never hardcode provider configuration inside modules — let the calling configuration set providers
- Create a root module per environment or stack (e.g., environments/production/main.tf calling child modules)
- Use module composition: root modules combine small modules; avoid deeply nested module hierarchies (max 2-3 levels)
- Version modules using git tags with semantic versioning; maintain a CHANGELOG.md
- Include at least one working example in examples/ directory for each module
- Test modules with Terratest, terraform test (built-in), or tftest framework