Terraform 15: Locals & string interpolation
easy⏱ 5 mincourseterraform
The locals block
A locals block defines values referenced as local.<name>. Unlike variable, locals are not inputs — they're computed inside the config from variables, other locals, or resource attributes. Use them to name a thing once and reuse it everywhere.
locals {
environment = "dev"
service = "orders"
location = "westus2"
# A naming convention computed once, reused everywhere.
name_prefix = "myorg-${local.service}-${local.environment}"
common_tags = {
environment = local.environment
service = local.service
managed_by = "terraform"
}
}
String interpolation ${...}
Inside a double-quoted HCL string, ${ ... } embeds any expression: variables, locals, function calls. This is how you assemble names and paths. Terraform functions like lower(...), format(...) and substr(...) are commonly nested inside ${...}.
resource "azurerm_resource_group" "app" {
name = "${local.name_prefix}-rg" # => myorg-orders-dev-rg
location = local.location
tags = local.common_tags
}
resource "azurerm_storage_account" "state" {
# names must be lowercase & no dashes: build with functions
name = lower("myorg${local.service}${local.environment}sa")
resource_group_name = azurerm_resource_group.app.name
location = local.location
}
locals vs variables
Rule of thumb: if the caller should set it, make it a variable. If it's derived from other values and callers should never override it, make it a local. Overusing locals for things that should be inputs makes a module rigid; overusing variables for derived values makes it noisy.
Build the naming convention
Write resourceName(env, service, type) that returns the lowercased, dash-joined name "{env}-{service}-{type}" — the TS twin of the local.name_prefix pattern. Log resourceName("dev", "orders", "rg") (expect "dev-orders-rg") and resourceName("PROD", "Billing", "kv") (expect "prod-billing-kv", note the lowercasing).