Terraform, an infrastructure-as-code (IaC) tool, provides a declarative way to define and provision infrastructure while ensuring consistency and scalability. However, handling Terraform deployments across different environments or projects can be challenging without a structured approach. Terraform variables can address these challenges by enabling dynamic configuration management, reducing code duplication, and improving maintainability. In this post we will dive deeper into one of the important topic of Terraform configuration - variable precedence.
Let's quickly review variable definition and assignment methods. Terraform supports different types of variables, including input variables, local values, environment variables, and outputs.
variable blocks
Input variables must be declared using variable blocks which may specify variable type, default value,
description, validation rule, and other optional arguments.
The most common way to define input variables is within a single file, called variables.tf.
Note, the name variables.tf does not have any special significance or built-in function. Terraform loads all
.tf files in the working directory, regardless of their names, and merges them into a single configuration
before execution. However, keeping all variable definitions in variables.tf is a widely accepted
convention that makes Terraform configurations more readable and maintainable.
Example: Defining and Using Input Variable
In this example, the value for project_id must be provided at the time of execution, while region has
a default value of "us-central1".
.tfvars files
Terraform also supports variable definitions files with extensions .tfvars and
.tfvars.json. It automatically loads terraform.tfvars, terraform.tfvars.json,
and *.auto.tfvars files found in the working directory.
Example: Defining Variables in terraform.tfvars File
Example: Defining Variables in terraform.tfvars.json File
TF_VAR_ environment variables
Terraform loads the values from environment variables with the names containing TF_VAR_ prefix
followed by a name of a declared variable.
Example: Setting TF_VAR_ Environment Variables
Terraform will automatically assign the values of TF_VAR_project_id and TF_VAR_region to
project_id and region when running terraform apply.
locals blocks
Local block assigns a name to a value or an expression and helps avoid repeating the same expression multiple
times in a module.
Example: Using Local Values
Here, local.environment is set to "dev", and local.vpc_name dynamically
generates the VPC name as "dev-vpc".
output blocksOutputs allow Terraform to display key information after execution, making it easier to retrieve values dynamically.
Example: Defining Outputs
After running terraform apply, you can retrieve the output with terraform output vpc_name.
Terraform variables help keep configurations modular, making deployments more flexible and manageable. In the next sections we will dive deeper into Terraform input variable precedence and illustrate how different sources of variables interact in a Terraform deployment.
As we just saw, Terraform provides multiple options for defining input variables. When the same variable is specified in different places, Terraform follows a specific precedence order to determine which value to use. Understanding this hierarchy is critical to avoid unexpected results when deploying infrastructure.
Terraform loads variables from multiple sources in a specific order and applies precedence rules outlined in the table below. Higher-precedence sources override lower-precedence ones when the same variable is defined in multiple places.
Summary Table: Terraform variable precedence order (highest to lowest)
| Precedence Rank |
Variable Source | Loaded Automatically? |
|---|---|---|
| 1 (Highest) | CLI -var flag CLI -var-file flag (applied in the provided order) |
❌ No (must be specified manually) |
| 2 | *.auto.tfvars files *.auto.tfvars.json files (loaded alphabetically) |
✅ Yes |
| 3 | terraform.tfvars.json |
✅ Yes |
| 4 | terraform.tfvars |
✅ Yes |
| 5 | Environment variables (TF_VAR_) |
✅ Yes |
| 6 (Lowest) | Default values in .tf files |
✅ Yes |
Explicit CLI flags (-var or -var-file) have the highest precedence, any value set here will override all
.tfvars files, environment variables, or defaults. Terraform loads variable values and files in the order they appear
on the command line and the last one wins.
The CLI -var flag is useful for quick testing but is not ideal for managing complex environments. Use the
-var-file flag in conjunction with custom .tfvars files (dev.tfvars, prod.tfvars,
etc.) when managing multiple environments or projects.
Terraform automatically loads variable values from the following files:
*.auto.tfvars files (highest rank among auto-loaded files). Files are processed in alphabetical order and
the last loaded value takes precedence. Use naming conventions (01-, 02-) to explicitly
control load orderterraform.tfvars.jsonterraform.tfvars (lowest rank among auto-loaded files)
Environment variables with the TF_VAR_ prefix override the default values set in .tf files but are
overridden by .tfvars files and CLI flags.
In the next section we will demonstrate how Terraform variables precedence works with the help of a few simple code examples.
We start our demonstration with a simple main.tf
file containing a singe variable with a default value assigned and then successively apply the following
variable definition files and assignment methods:
TF_VAR_ environment variableterraform.tfvars fileterraform.tfvars.json file01.auto.tfvars file01.auto.tfvars.json file02.auto.tfvars filevar-file.tfvars fileTo follow along with this demo you need a system with Terraform installed. You can find installation steps in this document - Install Terraform
main.tfLet's create a new project directory - tfvars-demo and add main.tf
file with the following content:
Run terraform apply -auto-approve. Terraform will display the default value of test_var
as set in the main.tf file:
TF_VAR_ environment variableAs the next step, run the following commands to set and check TF_VAR_test_var
environment variable:
Run terraform apply -auto-approve. Terraform will display the value of test_var loaded from the
TF_VAR_test_var environment variable (overriding the default value):
terraform.tfvars fileIn the working directory create terraform.tfvars containing the following lines:
Run terraform apply -auto-approve. Terraform will display the value of test_var
loaded from terraform.tfvars (overriding the value set by TF_VAR_test_var):
terraform.tfvars.json fileCreate terraform.tfvars.json containing the following lines:
Run terraform apply -auto-approve. Terraform will display the value of test_var loaded from
terraform.tfvars.json which overrides terraform.tfvars:
01.auto.tfvars file
In the working directory create 01.auto.tfvars containing the following lines:
Run terraform apply -auto-approve. Terraform will display the value of test_var loaded from
01.auto.tfvars which overrides terraform.tfvars.json:
01.auto.tfvars.json file
Create 01.auto.tfvars.json containing the following lines:
Run terraform apply -auto-approve. Terraform will display the value of test_var loaded from
01.auto.tfvars.json which overrides 01.auto.tfvars:
02.auto.tfvars file
Now create 02.auto.tfvars containing the following lines:
Run terraform apply -auto-approve. Terraform will display the value of test_var loaded from
02.auto.tfvars which overrides 01.auto.tfvars.json:
var-file.tfvars file
Create var-file.tfvars containing the following lines:
Run terraform apply -auto-approve -var="test_var=from: -var" -var-file=var-file.tfvars.
Terraform will display the value of test_var loaded form var-file.tfvars
which was the last loaded file:
Now run terraform apply -auto-approve -var-file=var-file.tfvars -var="test_var=from: -var"
(with the reversed order of CLI flags).
Terraform will display the value of test_var obtained form -var="test_var=from: -var"
which was the last parameter on the command line:
This completes the demonstration of various Terraform variable assignment methods with different precedence ranks.
Terraform offers flexible ways to define variables, including .tfvars files, environment variables,
CLI flags, and variable blocks in .tf files. This flexibility allows teams to customize configurations
dynamically while supporting different environments and deployment scenarios. However, with multiple precedence
layers, managing variables can become complex, potentially leading to unexpected behavior if not structured properly.
To maintain clarity and consistency, it is important to follow a methodical approach when defining and organizing Terraform variables. Here are some best practices:
variables.tf or terraform.tfvars, to avoid
duplication and inconsistencies..tfvars files for environment-specific configurations rather than hardcoding values in
.tf files.TF_VAR_*) to improve transparency.-var-file over -var CLI flags for better organization and repeatability.Understanding of Terraform variable precedence and following there recommendations helps avoid unexpected variable values and ensures correct environment configurations!
See Also:
Handling Terraform State in Multi-Environment Deployments
Terraform Value Types Tutorial
Terraform count Explained with Practical Examples
Terraform for_each Tutorial with Practical Examples
Exploring Terraform dynamic Blocks with GCP Examples
Working with External Data in Terraform
Handling Sensitive and Ephemeral Data in Terraform
Terraform Modules FAQ