DevOps Best Practices - Part 1
DevOps14 min read

Infrastructure as Code: Terraform Patterns That Scale

Organizing Terraform code for real-world projects. Modules, workspaces, state management, and team collaboration patterns.

TerraformIaCAWSDevOps

Beyond the Basics

Everyone can write basic Terraform. The challenge is organizing Terraform for teams, multiple environments, and growing infrastructure. Here are the patterns I've found work at scale.

Module Design

Good modules are the foundation of maintainable Terraform. A module should do one thing well and be reusable across environments.

hcl
# modules/vpc/main.tf
variable "environment" {
  type        = string
  description = "Environment name (staging, production)"
}

variable "cidr_block" {
  type        = string
  description = "VPC CIDR block"
}

variable "availability_zones" {
  type        = list(string)
  description = "AZs to use for subnets"
}

resource "aws_vpc" "main" {
  cidr_block           = var.cidr_block
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "${var.environment}-vpc"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# ... subnet creation, route tables, etc.

output "vpc_id" {
  value = aws_vpc.main.id
}

Environment Separation

Keep environments isolated. I use separate state files and separate directories for each environment:

text
terraform/
├── modules/
│   ├── vpc/
│   ├── eks/
│   └── rds/
├── environments/
│   ├── staging/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── terraform.tfvars
│   └── production/
│       ├── main.tf
│       ├── variables.tf
│       └── terraform.tfvars
└── backend.tf

State Management

Remote state with locking is non-negotiable for teams. I use S3 + DynamoDB for AWS projects:

hcl
terraform {
  backend "s3" {
    bucket         = "mycompany-terraform-state"
    key            = "environments/production/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

Never store state files in Git. They can contain secrets and will cause conflicts when multiple people work on infrastructure.

CI/CD Integration

Terraform changes should go through the same review process as application code. Here's my GitHub Actions workflow:

yaml
name: Terraform
on:
  pull_request:
    paths: ['terraform/**']

jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Terraform Init
        run: terraform init
        working-directory: terraform/environments/staging

      - name: Terraform Plan
        run: terraform plan -out=plan.tfplan
        working-directory: terraform/environments/staging

      - name: Comment Plan
        uses: actions/github-script@v7
        with:
          script: |
            // Post plan output as PR comment

Found this helpful?

I write about infrastructure, backend development, and DevOps. Follow along as I continue building.