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.json
terraform.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.tf
Let'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