TFLAB04-Variable Precedence: Six Ways to Set a Variable

Variable Precedence: Six Ways to Set a Variable

🔧 Terraform Core ⭐ Beginner terraform.tfvars .auto.tfvars -var -var-file TF_VAR_* Precedence

Scenario

Your team uses the same Terraform config for dev, staging, and prod. Different environments need different values — but the team is unsure which input method takes priority when the same variable is set in multiple places.

You need to demonstrate all six ways to set a variable and confirm the precedence order by setting the same variable via multiple methods simultaneously and observing which one wins.

Your Objectives
  • Declare a variable environment with a default of "from-default".
  • Create a terraform.tfvars file that sets environment = "from-tfvars".
  • Create a prod.auto.tfvars file that sets environment = "from-auto-tfvars".
  • Create a override.tfvars file that sets environment = "from-var-file".
  • Set TF_VAR_environment=from-env-var as an environment variable.
  • Pass -var="environment=from-cli" on the command line.
  • Output the resolved value and confirm the precedence order.

Additional Context

Terraform processes variable values in this order (lowest to highest priority):

  1. Default in the variable declaration
  2. Environment variables (TF_VAR_name)
  3. terraform.tfvars (auto-loaded)
  4. *.auto.tfvars (auto-loaded, alphabetical)
  5. -var-file flag (in order specified)
  6. -var flag (highest priority — always wins)

The rule is simple: more specific beats less specific. Defaults are the most general; a -var flag is the most targeted.

variables.tf

# variables.tf

variable "environment" {
  description = "Which environment are we deploying to?"
  type        = string
  default     = "from-default"   # Priority 1 (lowest)
}

variable "aws_region" {
  type    = string
  default = "us-east-1"
}

terraform.tfvars

# terraform.tfvars — auto-loaded by Terraform (Priority 3)
environment = "from-tfvars"

prod.auto.tfvars

# prod.auto.tfvars — auto-loaded, alphabetically after terraform.tfvars (Priority 4)
environment = "from-auto-tfvars"

override.tfvars

# override.tfvars — only loaded if passed with -var-file (Priority 5)
environment = "from-var-file"

main.tf

# main.tf

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

provider "aws" { region = var.aws_region }

resource "aws_s3_bucket" "demo" {
  bucket = "var-precedence-${var.environment}"
  tags   = { Environment = var.environment, ManagedBy = "terraform" }
}

outputs.tf

output "resolved_environment" {
  description = "The final value after all precedence rules are applied."
  value       = var.environment
}

Workflow Commands — Testing Precedence

terraform init

# Test 1: Only defaults (delete/rename tfvars files temporarily)
# Result: "from-default"

# Test 2: With terraform.tfvars present
terraform plan   # → "from-auto-tfvars" (auto.tfvars beats terraform.tfvars)

# Test 3: Add environment variable
export TF_VAR_environment="from-env-var"
terraform plan   # → "from-auto-tfvars" (auto.tfvars beats env var!)

# Test 4: Add -var-file flag
terraform plan -var-file="override.tfvars"   # → "from-var-file"

# Test 5: Add -var flag (HIGHEST PRIORITY)
terraform plan -var="environment=from-cli"   # → "from-cli" (always wins)

# Clean up env var
unset TF_VAR_environment
✓ Precedence Order (Lowest → Highest)
1. default          → "from-default"
2. TF_VAR_*         → "from-env-var"
3. terraform.tfvars → "from-tfvars"
4. *.auto.tfvars    → "from-auto-tfvars"
5. -var-file        → "from-var-file"
6. -var             → "from-cli"         ← ALWAYS WINS