Terraform Local Values and Expressions
Repeating the same value in ten different places is a maintenance problem. Change that value once and you must update it ten times — and risk missing one. Local values (locals) solve this by letting you define a value once and reuse it everywhere. Expressions let you compute and transform values dynamically. This topic covers both.
What Are Local Values
A local value assigns a name to an expression. Once defined, you reference that name anywhere in the configuration. Unlike input variables (which accept external values), locals are computed internally and cannot be set from outside.
Analogy: A Sticky Note on Your Desk
You have a project code — "PRJ-2024-ALPHA" — that appears on server names, bucket names, tags, and log groups. Instead of typing it 15 times, you write it on one sticky note and put it where you can see it. Every time you need it, you look at the note. Locals are that sticky note.
Declaring Locals
All local values go inside a single locals block. You can have multiple locals blocks across different files — Terraform merges them.
locals {
environment = "production"
project_name = "ecommerce-app"
region = "us-east-1"
# Computed from other locals
name_prefix = "${local.project_name}-${local.environment}"
common_tags = {
Project = local.project_name
Environment = local.environment
ManagedBy = "Terraform"
}
}
Reference locals with the local. prefix (singular — not locals.):
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.micro"
tags = local.common_tags
}
resource "aws_s3_bucket" "app_data" {
bucket = "${local.name_prefix}-data"
tags = local.common_tags
}
Diagram: One Local, Many Uses
locals {
name_prefix = "ecommerce-app-production"
}
|
|-----> aws_instance.web tags.Name = "ecommerce-app-production-web"
|-----> aws_s3_bucket.data bucket = "ecommerce-app-production-data"
|-----> aws_db_instance.db identifier= "ecommerce-app-production-db"
|-----> aws_lb.frontend name = "ecommerce-app-production-lb"
Update the local once and all four resources automatically use the new value.
Expressions in Terraform
An expression is any value that Terraform evaluates — a literal, a reference, or a computation. Expressions appear as argument values anywhere in your configuration.
String Interpolation
Embed expressions inside strings using ${...} syntax.
locals {
app_name = "myapp"
env = "prod"
full_name = "${local.app_name}-${local.env}"
# Result: "myapp-prod"
}
Conditional Expressions
Use a ternary expression to choose between two values based on a condition.
# Syntax: condition ? value_if_true : value_if_false
locals {
instance_type = var.environment == "prod" ? "t3.large" : "t3.micro"
}
If the environment is production, use the larger instance. Otherwise use the smaller one. One line replaces a whole block of if-else logic.
Arithmetic and Comparison Expressions
locals {
replica_count = var.environment == "prod" ? 3 : 1
storage_size_gb = var.base_storage * 2
is_large_env = var.replica_count > 2
}
Heredoc Strings for Multi-line Values
When a value spans multiple lines — such as a policy document or a startup script — use heredoc syntax.
locals {
user_data_script = <<-EOT
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
EOT
}
Practical Example: Centralising Tags
One of the most common uses of locals in real projects is centralising resource tags. Every cloud resource gets the same base tags, plus any resource-specific tags added on top.
locals {
base_tags = {
Project = var.project_name
Environment = var.environment
Owner = "platform-team"
ManagedBy = "Terraform"
}
}
resource "aws_instance" "api_server" {
ami = data.aws_ami.linux.id
instance_type = "t3.medium"
tags = merge(local.base_tags, {
Name = "api-server"
Role = "backend"
})
}
The merge() function combines two maps. The base tags apply to every resource; the resource-specific tags layer on top.
Key Points
- Local values define computed names inside a
localsblock and are referenced with thelocal.prefix. - Locals reduce repetition and make your configuration easier to update and read.
- Use string interpolation (
"${...}") to embed expressions inside strings. - Conditional expressions (
condition ? true_val : false_val) choose between values based on logic. - Centralising tags in a
local.common_tagsmap is a widely used best practice in real Terraform projects.
