How to Structure a Terraform Project - Best Practices for 2026

How to Structure a Terraform Project - Best Practices for 2026

Key Takeaway

Learn the best way to organize Terraform projects. Covers file structure, modules, environments, and naming conventions for scalable infrastructure code.

Table of Contents

Introduction

A well-structured Terraform project is easier to maintain, debug, and scale. This guide covers proven patterns for organizing your Terraform code, from simple single-environment setups to complex multi-environment architectures.

Basic Project Structure

For small projects or getting started:

project/
├── main.tf           # Primary resources
├── variables.tf      # Input variable declarations
├── outputs.tf        # Output declarations
├── terraform.tfvars  # Variable values
├── providers.tf      # Provider configuration
└── versions.tf       # Version constraints

main.tf

resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr
  tags       = local.common_tags
}

resource "aws_subnet" "public" {
  count             = length(var.public_subnets)
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.public_subnets[count.index]
  availability_zone = var.azs[count.index]
}

providers.tf

provider "aws" {
  region = var.region
}

versions.tf

terraform {
  required_version = ">= 1.5"
  
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Multi-Environment Structure

For projects with dev, staging, and production:

project/
├── modules/
│   ├── networking/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── compute/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── database/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
│   ├── staging/
│   │   ├── main.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
│   └── prod/
│       ├── main.tf
│       ├── terraform.tfvars
│       └── backend.tf
└── README.md

Module Best Practices

Create Reusable Modules

# modules/networking/main.tf
resource "aws_vpc" "this" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = merge(var.tags, { Name = "${var.name}-vpc" })
}

# modules/networking/variables.tf
variable "vpc_cidr" {
  type        = string
  description = "CIDR block for the VPC"
}

variable "name" {
  type        = string
  description = "Name prefix for resources"
}

# modules/networking/outputs.tf
output "vpc_id" {
  value = aws_vpc.this.id
}

Use Modules in Environments

# environments/prod/main.tf
module "networking" {
  source   = "../../modules/networking"
  vpc_cidr = "10.0.0.0/16"
  name     = "prod"
  tags     = local.common_tags
}

module "compute" {
  source        = "../../modules/compute"
  vpc_id        = module.networking.vpc_id
  instance_type = "t3.large"
}

Naming Conventions

Consistent naming makes code readable:

# Resources: snake_case, descriptive
resource "aws_instance" "web_server" {}
resource "aws_s3_bucket" "application_logs" {}

# Variables: snake_case
variable "instance_type" {}
variable "vpc_cidr_block" {}

# Outputs: snake_case, prefixed by resource
output "vpc_id" {}
output "web_server_public_ip" {}

# Modules: snake_case
module "networking" {}
module "web_application" {}

File Organization Rules

  1. One resource type per file for large projects
  2. Group related resources in smaller projects
  3. Always separate variables, outputs, and providers
  4. Use data sources in a dedicated data.tf file
  5. Keep locals in locals.tf

Hands-On Courses

Conclusion

Good project structure pays dividends as your infrastructure grows. Start simple, use modules for reusability, and maintain consistent conventions across your team.

🚀

Level Up Your Terraform Skills

Hands-on courses, books, and resources from Luca Berton

Luca Berton
Written by

Luca Berton

DevOps Engineer, AWS Partner, Terraform expert, and author. Creator of Ansible Pilot, Terraform Pilot, and CopyPasteLearn.