2.05 Terraform Variable Types
Overview
Terraform variables support a range of types — from simple primitives like string, number, and bool, to complex structures like list, map, set, object, and tuple. Using the correct type constraint catches misconfiguration early and makes modules self-documenting.
Abstract
The type argument in a variable block is optional but strongly recommended. When omitted, Terraform defaults to any, accepting values of any type. Explicit type constraints enforce correctness at plan time, before any infrastructure is touched.
Why It Matters in Production
- Type constraints catch invalid variable values before
apply, preventing mid-deployment failures - Complex types (
object,map) allow entire environment configurations to be passed as a single variable, reducing the number of individual declarations listandmaptypes enable dynamic resource creation usingfor_eachandcount- Mismatched types produce clear, actionable errors rather than silent misconfiguration
Variable Type Reference
| Type | Example Value | Notes |
|---|---|---|
string |
"/root/pets.txt" |
Alphanumeric single value |
number |
1, -5, 3.14 |
Positive or negative |
bool |
true / false |
Boolean flag |
any |
Any value | Default when type is omitted |
list |
["cat", "dog"] |
Ordered, indexed from 0, allows duplicates |
map |
pet1 = cat |
Key-value pairs |
set |
["cat", "dog"] |
Like a list but no duplicate elements allowed |
object |
Complex data structure | Mix of named attributes with different types |
tuple |
Complex data structure | Ordered sequence with fixed mixed types |
Variable Block — Full Syntax
variable "<name>" {
description = "What this variable is for"
type = <type>
default = <value>
sensitive = false
}
Basic type examples
variable "filename" {
default = "/root/pets.txt"
type = string
description = "the path of local file"
}
variable "length" {
default = 2
type = number
description = "length of the pet name"
}
variable "password_change" {
default = true
type = bool
}
List
A list is an ordered, indexed collection of values. Elements are referenced by their zero-based index using var.<name>[index].
Index reference:
| Index | Value |
|---|---|
| 0 | Mr |
| 1 | Mrs |
| 2 | Sir |
List with type constraint
# List of strings (valid)
variable "prefix" {
default = ["Mr", "Mrs", "Sir"]
type = list(string)
}
# List of numbers (valid)
variable "prefix" {
default = [1, 2, 3]
type = list(number)
}
Type mismatch error
Declaring type = list(number) but providing string defaults causes a plan-time error:
Map
A map stores data as key-value pairs. Values are accessed by key using var.<name>["key"].
# variables.tf
variable "file-content" {
type = map
default = {
"statement1" = "We love pets!"
"statement2" = "We love animals!"
}
}
# main.tf
resource "local_file" "my-pet" {
filename = "/root/pets.txt"
content = var.file-content["statement2"] # "We love animals!"
}
Key-value reference:
| Key | Value |
|---|---|
| statement1 | We love pets! |
| statement2 | We love animals! |
Map with type constraint
# Map of strings
variable "cats" {
default = {
"color" = "brown"
"name" = "bella"
}
type = map(string)
}
# Map of numbers
variable "pet_count" {
default = {
"dogs" = 3
"cats" = 1
"goldfish" = 2
}
type = map(number)
}
Set
A set is like a list but does not allow duplicate elements. Attempting to use duplicate values causes a plan-time error.
# Valid — no duplicates
variable "prefix" {
default = ["Mr", "Mrs", "Sir"]
type = set(string)
}
variable "fruit" {
default = ["apple", "banana"]
type = set(string)
}
variable "age" {
default = [10, 12, 15]
type = set(number)
}
Duplicate element error
# Invalid — "Sir" appears twice
variable "prefix" {
default = ["Mr", "Mrs", "Sir", "Sir"]
type = set(string)
}
# Invalid — "banana" appears twice
variable "fruit" {
default = ["apple", "banana", "banana"]
type = set(string)
}
# Invalid — 10 appears twice
variable "age" {
default = [10, 12, 15, 10]
type = set(number)
}
List vs Set:
| Feature | list |
set |
|---|---|---|
| Ordered | ✅ Yes | ❌ Not guaranteed |
| Index access | ✅ var.name[0] |
❌ No index access |
| Duplicates allowed | ✅ Yes | ❌ No |
Object
An object combines multiple named attributes of different types into a single variable — useful for grouping related configuration together.
# variables.tf
variable "bella" {
type = object({
name = string
color = string
age = number
food = list(string)
favorite_pet = bool
})
default = {
name = "bella"
color = "brown"
age = 7
food = ["fish", "chicken", "turkey"]
favorite_pet = true
}
}
Object attribute reference:
| Key | Example Value | Type |
|---|---|---|
| name | bella | string |
| color | brown | string |
| age | 7 | number |
| food | ["fish", "chicken", "turkey"] | list(string) |
| favorite_pet | true | bool |
Tuple
A tuple is an ordered sequence of elements with fixed, mixed types. Unlike a list (same type throughout), each position in a tuple has its own declared type, and the element count must match exactly.
# variables.tf — valid
variable "kitty" {
type = tuple([string, number, bool])
default = ["cat", 7, true]
}
Tuple length/type mismatch error
Adding an extra element or using the wrong type causes a plan-time error:
List vs Tuple:
| Feature | list |
tuple |
|---|---|---|
| Element types | All the same | Each position has its own type |
| Length | Variable | Fixed at declaration |
| Use case | Homogeneous collections | Fixed-schema sequences |
Best Practices
Best Practices
- Always specify
typein variable blocks — it documents intent and catches errors at plan time rather than apply time. - Use
objectto group related variables (e.g. all properties of a server) instead of declaring many separate variables. - Use
map(string)ormap(number)rather than plainmapto enforce consistent value types across all keys. - Prefer
list(string)overlistso Terraform validates element types. - Use
setinstead oflistwhen order doesn't matter and uniqueness must be guaranteed (e.g. security group rules, tag sets). - Add
descriptionto every variable, especially complex types, so module consumers know what structure to provide.
Security Best Practices
Security
- Use
sensitive = trueon any variable that holds a password, token, or key — regardless of its type (works withstring,object, etc.). - Avoid storing complex
objectvariables with secrets indefault— the default value is stored in state in plaintext. - When using
mapvariables to pass environment configs, ensure the map does not include keys that hold secrets unless the variable is markedsensitive.
Do and Don't
| ✅ Do | ❌ Don't |
|---|---|
Use type = list(string) to constrain element types |
Use bare type = list in shared modules |
Use object to group related attributes into one variable |
Create dozens of individual variables for logically related data |
Use set when uniqueness of elements must be enforced |
Use list when duplicates would cause incorrect behaviour |
Match default values to the declared type |
Provide string defaults for a list(number) variable |
Access list elements with var.name[index] |
Try to use index access on a set — sets are unordered |
Common Mistakes
Common Mistakes
- Type/default mismatch: Declaring
type = list(number)with string defaults (e.g.["Mr", "Mrs"]) causes a plan error. Default values must match the declared type. - Duplicate values in a set: Sets enforce uniqueness — adding a repeated element causes an immediate error.
- Exceeding tuple length: A tuple type declaration is a contract — providing more or fewer elements than declared types always fails.
- Using index access on a set: Unlike lists, sets have no guaranteed order and do not support index (
[0]) access. - Bare
maporlistwithout subtype: Works, but allows mixed types in values/elements, which causes unexpected behaviour in modules andfor_eachloops.
Quick Recap
- Terraform has three primitive types (
string,number,bool) and five complex types (list,map,set,object,tuple) typeis optional — omitting it defaults toany, but explicit types are always preferred- List: ordered, indexed from 0, duplicates allowed — access with
var.name[index] - Map: key-value pairs — access with
var.name["key"] - Set: like a list but no duplicates and no guaranteed order
- Object: named attributes of mixed types — defines a schema for complex variables
- Tuple: fixed-length sequence where each position has a declared type
- Type mismatches and constraint violations are caught at
terraform planbefore any infrastructure changes
Interview / Revision Notes
Revision
- What is the default type if
typeis omitted from a variable block?any. - What is the difference between a list and a set? A list allows duplicates and supports index access; a set does not allow duplicates and has no guaranteed order.
- What is the difference between a list and a tuple? A list contains elements of the same type; a tuple has a fixed length where each position can have a different type.
- How do you access the second element of a list variable named
prefix?var.prefix[1](zero-based index). - How do you access a map value by key?
var.<map_name>["<key>"]. - What error occurs if a
setvariable has duplicate default values? Terraform throws a plan-time error — sets require all elements to be unique. - When would you use
objectover multiple separate variables? When grouping logically related attributes (e.g. all properties of a server or pet) into a single, schema-enforced variable.