Essential Terraform best practices for organizing and structuring your infrastructure code:

1. Separate Configuration Files

Instead of putting all code in main.tf, distribute it across multiple files:

  • main.tf: Calls modules, locals, and data sources to create all resources
  • variables.tf: Contains variable declarations used in main.tf. Place required variables at the top and optional ones at the bottom, separated by a comment line for better readability
  • outputs.tf: Contains outputs from resources created in main.tf
  • versions.tf: Contains Terraform and provider version requirements
  • data.tf: Contains data source imports
  • resource.tf: Contains specific resource declarations
  • terraform.tfvars: Contains variable values. Should not be used anywhere else

2. Order Variable Block Keys

In variables.tf, order keys as follows: description, type, default, validation.

3. Use Dynamic Blocks

Dynamic blocks enable more flexible and automated configurations. They generate repeating code blocks based on input data, simplifying infrastructure management and reducing code duplication.

4. Keep Resource Modules Simple

Strive to make your resource modules as simple as possible.

5. Specify Module Versions

Always specify versions for your modules to avoid unexpected issues during deployments. Use semantic versioning when updating modules.

6. Combine Tightly Coupled Modules

If your modules are tightly coupled, combine them into one. Store such modules in a single repository and use them as submodules. This allows you to version them as a single unit and simplifies management.

7. Use map Instead of list for Object Groups

When creating a group of identical objects, use map instead of list. With map, resources will be updated. With list, resources are recreated, which can be critical for some scenarios.