Skip to main content

tfvars File

A .tfvars file (terraform.tfvars or *.auto.tfvars) contains values for Terraform input variables, keeping configuration values separate from variable declarations. Different .tfvars files for dev, staging, and production let you reuse the same infrastructure code with environment-specific settings.

What Is a Terraform tfvars File?

A .tfvars file is where you set the actual values for your Terraform variables. Your variables.tf declares what variables exist and what types they are. Your .tfvars file fills in the values for a specific environment or context.

Think of it as the difference between a form template and a filled-in form. variables.tf is the blank form with field names and rules. prod.tfvars is the form filled out with production values.

At Razorpay, the CI/CD pipeline runs terraform apply -var-file=prod.tfvars for production and terraform apply -var-file=dev.tfvars for development. The infrastructure code is identical — only the variable files differ. When a new environment is needed, create a new .tfvars file.

◈ DIAGRAM
+------------------------------------------+
| variables.tf (declarations) |
| variable "environment" { type = string } |
| variable "instance_type" { type = string}|
| variable "replica_count" { type = number}|
+------------------------------------------+
|
+-----------+-----------+
| |
v v
+------------------+ +-------------------+
| dev.tfvars | | prod.tfvars |
| environment | | environment |
| = "dev" | | = "prod" |
| instance_type | | instance_type |
| = "t3.micro" | | = "t3.large" |
| replica_count | | replica_count |
| = 1 | | = 3 |
+------------------+ +-------------------+

tfvars File Format

HCL
# terraform.tfvars — basic syntax
# Strings
environment = "dev"
aws_region = "ap-south-1"
project_name = "razorpay-payments"
# Numbers
replica_count = 2
rds_allocated_storage = 20
# Booleans
enable_multi_az = false
enable_deletion_protection = false
# Lists
availability_zones = ["ap-south-1a", "ap-south-1b"]
allowed_cidr_blocks = [
"10.0.0.0/8",
"172.16.0.0/12",
]
# Maps
instance_types = {
dev = "t3.micro"
staging = "t3.small"
prod = "t3.large"
}
# Objects — match the variable type exactly
database_config = {
engine = "postgres"
engine_version = "14.9"
instance_class = "db.t3.micro"
allocated_storage_gb = 20
multi_az = false
backup_retention_days = 3
}

Auto-Loading vs Explicit Loading

Bash
# These files are auto-loaded — Terraform reads them without being told
terraform.tfvars # always auto-loaded if present
terraform.tfvars.json # JSON format, also auto-loaded
*.auto.tfvars # any file ending in .auto.tfvars
# e.g.: common.auto.tfvars, secrets.auto.tfvars
# Explicit load — you must pass these with -var-file
terraform plan -var-file=dev.tfvars
terraform plan -var-file=prod.tfvars
terraform apply -var-file=staging.tfvars

Per-Environment File Pattern

Bash
# Recommended directory structure
.
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
├── terraform.tfvars # default/dev values (auto-loaded)
├── dev.tfvars # override for dev
├── staging.tfvars # override for staging
├── prod.tfvars # override for prod
└── terraform.tfvars.example # template showing all required variables
Bash
# CI/CD pipeline
# Dev deploy
terraform apply -var-file=dev.tfvars
# Staging deploy
terraform apply -var-file=staging.tfvars
# Production deploy
terraform apply -var-file=prod.tfvars

What NOT to Put in tfvars Files

HCL
# BAD — do not put secrets in tfvars files committed to Git
db_master_password = "S3cr3tP@ss" # NEVER in .tfvars committed to Git
api_key = "sk-abc123xyz" # NEVER in .tfvars committed to Git
# GOOD — use environment variables for secrets
# export TF_VAR_db_master_password="S3cr3tP@ss"
# export TF_VAR_api_key="sk-abc123xyz"
# Then terraform apply reads TF_VAR_ automatically

The .tfvars.example Pattern

HCL
# terraform.tfvars.example — commit this to Git
# Shows all required variables without values
# New engineers copy this and fill in their values
aws_region = "" # e.g., "ap-south-1"
environment = "" # dev, staging, or prod
project_name = "" # e.g., "razorpay-payments"
database_config = {
engine = "postgres" # do not change
engine_version = "14.9" # do not change
instance_class = "" # e.g., "db.t3.medium"
allocated_storage_gb = 20
multi_az = false # set true for prod
backup_retention_days = 7
}
# db_master_password — DO NOT set here
# Set via: export TF_VAR_db_master_password="your-password"

.gitignore Rules for tfvars Files

Bash
# .gitignore — what to exclude
# Never commit state files
terraform.tfstate
terraform.tfstate.backup
*.tfstate
*.tfstate.backup
# Never commit the .terraform directory (downloaded providers/modules)
.terraform/
.terraform.lock.hcl # DO commit this — it locks provider versions
# Never commit auto.tfvars files that may contain secrets
*.auto.tfvars
*.auto.tfvars.json
# You CAN commit terraform.tfvars if it has no secrets
# You CAN commit dev.tfvars, staging.tfvars, prod.tfvars if they have no secrets
# You MUST commit terraform.tfvars.example for documentation

Variable Precedence — Where tfvars Files Fit

Bash
Priority order (highest wins):
1. -var flag on command line
terraform plan -var="environment=prod"
2. TF_VAR_ environment variables
export TF_VAR_environment="prod"
3. *.auto.tfvars (alphabetical)
common.auto.tfvars
4. terraform.tfvars (auto-loaded)
5. default values in variable {} blocks
variable "environment" { default = "dev" }

Troubleshooting tfvars Files

Error Root Cause Fix
Error: No value for required variable Variable has no default and not in any tfvars Add value to tfvars or set TF_VAR_
Error: Invalid expression Syntax error in tfvars Check for missing quotes or commas
Error: Variables not allowed Trying to use var.x inside tfvars tfvars values are literals, not expressions
Values not loading Wrong filename or wrong directory Confirm filename ends in .tfvars, run from correct directory
Object type mismatch tfvars object has wrong keys Match keys exactly to the object({}) type in variables.tf
Remember

Commit terraform.tfvars.example to Git as a template, but be careful with terraform.tfvars — auto-load means it applies to every terraform plan and apply run in that directory. If it has environment-specific values, switching environments requires editing or replacing the file.

Common Mistake

Creating .auto.tfvars files for secrets. Any file ending in .auto.tfvars is loaded automatically — if you create secrets.auto.tfvars with passwords and commit it to Git, those secrets are now in your repository history permanently. Use TF_VAR_ environment variables for all secret values.

Frequently Asked Questions

What's the actual precedence order when multiple .tfvars files and CLI flags define the same variable?

Terraform applies values in increasing precedence: environment variables (`TF_VAR_x`) first, then `terraform.tfvars` if present, then any `*.auto.tfvars` files in alphabetical order, then `-var-file` flags in the order given on the command line, and finally `-var` flags on the command line win over everything. This matters when a CI pipeline passes `-var-file=prod.tfvars` but a stray `terraform.tfvars` also sits in the directory — the auto-loaded file's values can unexpectedly override what the pipeline intended if precedence isn't understood.

What's a common security mistake with tfvars files specifically?

Committing a .tfvars file containing real secrets (API keys, database passwords) to version control because it 'looked like just config values.' Unlike the state file, this mistake is entirely avoidable — .tfvars files should be gitignored when they carry sensitive values, with secrets instead injected via environment variables, a secrets manager, or a CI-only variable file that never touches the repo. Committing example/template tfvars with placeholder values is fine and often useful for documentation.