DEV Community

Cover image for -> Day-06 AWS Terraform Project Structure
Amit Kushwaha
Amit Kushwaha

Posted on

-> Day-06 AWS Terraform Project Structure

As Terraform projects grow, keeping all configurations inside a single main.tf becomes difficult to manage. A well-organized file structure makes your Infrastructure as Code easier to read, scale, and maintain. Today’s focus is on learning how Terraform loads files and how to structure them properly.


How Terraform Loads Files

Before organizing resources into different files, it’s important to understand how Terraform treats them:

  • Terraform loads all .tf files in the same directory.
  • Files are processed in alphabetical (lexicographical) order.
  • File names do not impact how Terraform behaves.
  • All .tf files are merged into one configuration internally.

This means the file structure exists mainly for users, not for Terraform. You can divide files however you prefer as long as the content itself is valid.


Recommended Terraform File Structure

A clean and readable Terraform project often uses a structure like this:

project-root/
├── backend.tf          # Remote backend configuration
├── provider.tf         # Providers and default settings
├── variables.tf        # Input variables
├── locals.tf           # Local values (naming, tags)
├── main.tf             # General resources
├── vpc.tf              # VPC and networking        
├── outputs.tf          # Output values
├── terraform.tfvars    # Values for variables
└── README.md           # Documentation

Enter fullscreen mode Exit fullscreen mode

This structure separates responsibilities clearly and keeps the project easy to navigate.


Why This Structure Helps

  1. Separation of Concerns
    Different resources stay in different files (networking, compute, storage, etc.).

  2. Easier Collaboration
    Multiple team members can work on different parts without conflicts.

  3. Readability
    It becomes easier to find specific resources or edit configurations.

  4. Scalability
    As infrastructure grows, the structure remains manageable.


Reorganized Terraform Code
The simplified and clean version of the restructured files based on the given configuration.


backend.tf

terraform {
  backend "s3" {
    bucket         = "my-aws-terraform-demo-bucket-123456789"
    key            = "dev/terraform.tfstate"
    region         = "us-east-1"
    use_lockfile  = "true"
    encrypt        = true
  }
}
Enter fullscreen mode Exit fullscreen mode

provider.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "6.23.0"
    }
  }
}

provider "aws" {
  region = var.region
}

Enter fullscreen mode Exit fullscreen mode

variables.tf

variable "region" {
  description = "AWS Region"
  type        = string
}

variable "environment" {
  description = "Environment name like dev, stage, prod"
  type        = string
}
variable "ami_id" {
  description = "AMI ID for the ec2 instance"
  type        = string
}

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
}

variable "bucket_name" {
  description = "S3 Bucket name"
  type        = string
}

variable "vpc_cidr_block" {
  description = "CIDR block for the VPC"
  type        = string
}
Enter fullscreen mode Exit fullscreen mode

locals.tf

locals {
  common_tags = {
    Environment = var.environment
    Project     = "Terraform-Demo"
    Owner       = "DevOps-Team"
  }

  #   full bucket name with environment prefix
  full_bucket_name = "${var.environment}-${var.bucket_name}-${random_string.suffix.result}"
}
Enter fullscreen mode Exit fullscreen mode

main.tf

resource "aws_instance" "my_instance" {
  ami           = var.ami_id
  instance_type = var.instance_type
}

resource "aws_s3_bucket" "terraform_bucket" {
  bucket = var.bucket_name
}

resource "aws_vpc" "terraform_vpc" {
  cidr_block = var.vpc_cidr_block
}
Enter fullscreen mode Exit fullscreen mode

outputs.tf

resource "aws_instance" "my_instance" {
  ami           = var.ami_id
  instance_type = var.instance_type
}

resource "aws_s3_bucket" "terraform_bucket" {
  bucket = var.bucket_name
}

resource "aws_vpc" "terraform_vpc" {
  cidr_block = var.vpc_cidr_block
}
Enter fullscreen mode Exit fullscreen mode

terraform.tfvars

region         = "us-east-1"
environment    = "dev"
ami_id         = "ami-id"
instance_type  = "t2.micro"
bucket_name    = "my-aws-terraform-demo-bucket-123456789"
vpc_cidr_block = "10.0.0.0/16"
Enter fullscreen mode Exit fullscreen mode

Best Practices for File Organization

  • Use clear and consistent naming.
  • Group similar resources together.
  • keep files focused on specific areas.
  • Avoid putting everything in main.tf.
  • Document your structure in a README.
  • Use modules for reusable components.
  • Keep files readable and under manageable size.

Useful Commands

terraform validate
terraform fmt -recursive
terraform plan
terraform apply
Enter fullscreen mode Exit fullscreen mode

Common Mistakes to avoid

  • Keeping all resources in a sinle file.
  • Mixing unrelated services in the same file.
  • Using unclear or inconsistent file names.
  • Not documenting how the project is structured.
  • Creating overly complex folder structures for small projects.

Connect With Me

If you enjoyed this post or want to follow my #30DaysOfAWSTerraformChallenge journey, feel free to connect with me here:

💼 LinkedIn: Amit Kushwaha

🐙 GitHub: Amit Kushwaha

📝 Hashnode / Amit Kushwaha

🐦 Twitter/X: Amit Kushwaha

Top comments (0)