7 Terraform Mistakes Even Senior Engineers Make
After 8 years of shipping infrastructure at Sephora, Bradesco, and Indeed — these are the mistakes I still see in production Terraform codebases.

I've reviewed Terraform codebases at companies processing millions of requests per day. The same mistakes show up everywhere — even from engineers with 10+ years of experience.
Here are seven I see repeatedly, and how to fix them.
1. Hardcoding Values Instead of Using Variables
# Bad
resource "azurerm_resource_group" "this" {
name = "rg-production-eastus"
location = "eastus"
}
# Good
resource "azurerm_resource_group" "this" {
name = "rg-${var.environment}-${var.location}"
location = var.location
}
The hardcoded version works until you need staging. Then you copy-paste the file, change two strings, and maintain two identical files forever. Variables cost you 30 seconds upfront and save hours later.
2. Not Using Remote State
If your .tfstate file lives on your laptop, you have a single point of failure that also prevents your team from collaborating.
terraform {
backend "azurerm" {
resource_group_name = "rg-terraform-state"
storage_account_name = "stterraformstate"
container_name = "tfstate"
key = "prod.tfstate"
}
}
Remote state with locking (Azure Storage, S3 + DynamoDB, GCS) is non-negotiable for any team larger than one person.
3. Ignoring the Plan Output
terraform apply without reading terraform plan is like merging a PR without reviewing the diff. The plan tells you exactly what will be created, changed, or destroyed. Read it.
Especially dangerous: resources that show must be replaced. This means Terraform will destroy and recreate the resource — which can mean downtime, data loss, or both.
4. Storing Secrets in Terraform Files
# Never do this
resource "azurerm_postgresql_flexible_server" "db" {
administrator_password = "SuperSecret123!"
}
Use TF_VAR_ environment variables, Key Vault references, or a secrets manager. Secrets in .tf files end up in state files, version control, and CI logs.
5. Not Tagging Resources
Six months from now, you'll have 47 resources in your Azure subscription and no idea which project owns what. Tags fix this:
locals {
common_tags = {
project = "my-saas"
environment = "production"
managed_by = "terraform"
owner = "platform-team"
}
}
Apply common_tags to every resource. Your future self (and your finance team) will thank you.
6. One Giant main.tf File
A 2,000-line main.tf is not infrastructure as code — it's infrastructure as novel. Split by concern:
infra/
├── main.tf # Provider, backend
├── network.tf # VNet, subnets, NSGs
├── compute.tf # VMs, App Service, AKS
├── database.tf # PostgreSQL, Redis
├── monitoring.tf # Log Analytics, alerts
├── variables.tf # Input variables
├── outputs.tf # Outputs
└── terraform.tfvars # Environment values
Each file should be readable in under 2 minutes.
7. Not Destroying After Testing
Cloud resources cost money every second they exist. After testing:
terraform destroy -auto-approve
az group list -o table # Verify zero resources
I've seen engineers leave AKS clusters running for months because they forgot. That's $200+/month burning silently.
The Real Lesson
Terraform is simple to learn and hard to master. The difference between junior and senior Terraform is not knowing more resources — it's knowing how to structure, version, and maintain the code over time.
I'm building a 24-episode YouTube series teaching all of this from zero. All code is open source on GitHub. If you want the video version, check out my channel.
Join the Newsletter
Subscribe to get my latest content by email.
We won't send you spam. Unsubscribe at any time.