Infrastructure as Code — Terraform Patterns That Scale
Infrastructure as Code (IaC) is not just writing config files—it’s about designing infrastructure that is modular, scalable, and maintainable. In this article, we’ll cover Terraform patterns that have been proven to scale in production environments.
1. Modular Design
Why Modular?
- Avoid copy-pasting code
- Enable reusability and testing
- Maintain separation of concerns
How to Structure
modules/
vpc/
eks/
rds/
s3/
alb/
environments/
staging/
main.tf
variables.tf
production/
main.tf
variables.tf
Use input variables and outputs to make modules flexible:
# modules/vpc/variables.tf
variable "cidr_block" {
type = string
}
# modules/vpc/main.tf
resource "aws_vpc" "main" {
cidr_block = var.cidr_block
}
Then call the module:
module "vpc" {
source = "../../modules/vpc"
cidr_block = "10.0.0.0/16"
}
2. Workspaces for Environment Isolation
Instead of duplicating code per environment:
terraform workspace new staging
terraform workspace new production
Use workspace-aware configurations:
locals {
env = terraform.workspace
}
resource "aws_s3_bucket" "logs" {
bucket = "my-app-logs-${local.env}"
}
🧠 Pro Tip: Use
terragrunt
oratmos
if your project grows beyond a few modules.
3. Remote State with Locking
Always store state remotely with locking enabled:
terraform {
backend "s3" {
bucket = "my-tf-state"
key = "envs/prod/terraform.tfstate"
region = "ap-southeast-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
Why?
- Enables collaboration
- Prevents state corruption
- Auditability
4. Code Organization with Terragrunt (Advanced)
Terragrunt enables DRY configuration across environments:
live/
prod/
vpc/
eks/
staging/
vpc/
eks/
modules/
vpc/
eks/
With a terragrunt.hcl
per component:
terraform {
source = "../../modules/vpc"
}
include {
path = find_in_parent_folders()
}
inputs = {
cidr_block = "10.0.0.0/16"
}
5. Tagging and Naming Conventions
Use standardized tags across all resources:
locals {
common_tags = {
Environment = terraform.workspace
Owner = "devops-team"
Project = "hasan-app"
}
}
resource "aws_instance" "web" {
ami = "ami-123456"
instance_type = "t3.micro"
tags = local.common_tags
}
Use naming standards like:
<project>-<env>-<component>
# e.g., hasanapp-prod-vpc
6. Security Practices
- Use
aws_iam_policy_document
to generate IAM policies instead of raw JSON - Store secrets in AWS Secrets Manager or Vault, and reference via
data
blocks - Avoid hardcoded credentials; use environment variables or identity-based access (OIDC)
Example:
data "aws_secretsmanager_secret_version" "db_password" {
secret_id = "rds-db-password"
}
output "db_password" {
value = data.aws_secretsmanager_secret_version.db_password.secret_string
sensitive = true
}
7. Plan & Apply Automation with CI/CD
Integrate Terraform into your deployment pipeline:
Example GitHub Actions:
name: Terraform CI
on:
push:
branches: [main]
jobs:
terraform:
name: "Terraform Plan & Apply"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
- name: Terraform Plan
run: terraform plan
- name: Terraform Apply
run: terraform apply -auto-approve
if: github.ref == 'refs/heads/main'
🔐 Secure your CI/CD secrets using GitHub Encrypted Secrets or OpenID Connect.
8. Blue-Green or Canary Infra Rollout
Use feature flags and infrastructure abstraction:
Example: Toggle ALB target group
variable "active_target_group" {
default = "blue"
}
resource "aws_lb_listener_rule" "forward" {
listener_arn = aws_lb_listener.app.arn
actions = [
{
type = "forward"
target_group_arn = var.active_target_group == "blue" ? aws_lb_target_group.blue.arn : aws_lb_target_group.green.arn
}
]
}
For canary, use AWS AppConfig or feature toggling frameworks to gradually shift traffic.
Conclusion
Terraform at scale requires more than just .tf
files — it needs structure, automation, and discipline. By following these patterns, your infrastructure can grow without turning into a spaghetti mess.
Do you have a favorite infrastructure pattern that wasn’t covered here? Let’s discuss it together on LinkedIn.
🔗 Read more
Coming next: Observability for DevOps — Logs, Metrics, Traces, and Beyond.