string, number, and bool. You then combine those primitives with collection types (list, map, set) to model complex inputs like network lists, resource tags, or unique identifiers.
Primitive types
- String: free-form text for names, tags, DNS names, and other textual values.
- Number: integers or floating-point values for counts, sizes, timeouts, etc.
- Boolean:
true/falseswitches for toggles (e.g., enabling or disabling features).
"three" for a number variable).
Declaring explicit types helps catch errors early. For example, if someone supplies the word
three instead of the numeric value 3 for a number variable, Terraform will report a type validation error before any infrastructure changes occur.Lists
Lists store an ordered sequence of values. Use lists when order matters or when you need indexed access to a sequence of similar items (availability zones, instance sizes, subnet CIDRs, etc.). Example list variable:- Values are accessed by index, starting at zero (e.g.,
var.permitted_size[0]). - Lists preserve order — use them when sequence matters.
- Accessing an out-of-range index will cause an error, so validate or guard your indexing.
Maps
Maps are unordered key-value collections and are useful when you prefer name-based access rather than positional indexing. Example map variable:- Readable, self-documenting keys (e.g.,
var.course_details.instructor). - Add or modify keys without affecting others.
- Unordered by design — do not rely on entry order.
Sets
Sets are unordered collections that enforce uniqueness. Use sets when duplicates must be avoided (subnet IDs, IP addresses, domain names). Example set variable:- Values are unique; duplicates are automatically deduplicated.
- Sets are unordered; you cannot index into a set (no
set[0]). - Convert a set to a list with
tolist()when you need deterministic ordering and indexed access. - Use
toset()in literals to ensure Terraform treats the default as a set rather than a list.
Sets are ideal when uniqueness matters. If you later need ordered access, convert a set to a list with
tolist() and handle the ordering explicitly.Referencing variables
Terraform variable values are referenced using thevar namespace followed by the variable name. This distinguishes variables from literal values inside your configuration.
Example variable definitions (vSphere):
var.vsphere_datacenterreturns the string value"prd-workload-dc".var.vsphere_networks[0]returns the first element of the list ("VM Network"). Remember lists are zero-indexed.
Table: Terraform variable types at a glance
| Type | Purpose | Example HCL |
|---|---|---|
Primitive: string | Names, tags, DNS | variable "region" { type = string } |
Primitive: number | Counts, sizes, timeouts | variable "num_of_vms" { type = number } |
Primitive: bool | Feature toggles | variable "enable_ha" { type = bool } |
Collection: list(T) | Ordered sequences, indexing | variable "permitted_size" { type = list(string) } |
Collection: map(T) | Named lookups, self-documenting | variable "course_details" { type = map(string) } |
Collection: set(T) | Unordered unique values | variable "pub_subnet_ids" { type = set(string) } |
Best practices and tips
- Prefer explicit
typedeclarations to avoid accidental values and to enable early validation. - Use
listwhen order matters and you need indexed access. - Use
mapfor named lookups and to make intent clear in your inputs. - Use
setwhen you need uniqueness; convert withtolist()when deterministic ordering is required. - Validate indexes or use helper functions (e.g.,
length(),lookup()) to avoid runtime errors. - Consider
variablevalidationblocks (Terraform 0.13+) for enforcing constraints beyond type (e.g., allowed values, regex checks).
Summary
- The three primitive types (
string,number,bool) form the foundation of Terraform variables. - Lists, maps, and sets are the primary collection types; choose based on order, naming, and uniqueness requirements.
- Always reference variables as
var.<name>and validate indexes and types before runtime.
validation rules to enforce more complex constraints and business rules in your variable definitions.