Variables and outputs
Declaring input variables
A variable block declares an input variable, one value a module (a directory of configuration Terraform evaluates as a unit) accepts from its caller, and optionally constrains and documents it:
variable "instance_count" {
type = number
description = "How many app servers to create"
default = 2
}
variable "db_password" {
type = string
sensitive = true
}
The label after variable is the variable's name, and inside the module you read its value as var.instance_count, never as the bare instance_count. Referring to it by the bare name is a syntax error, not a silent fall-through to null. Everything else in the block is optional and shapes how a value is accepted. Declaring a variable, choosing where its value comes from, and handing results back out through output blocks are the three moves this page walks through.
The arguments a variable block accepts
A variable block supports a fixed set of optional arguments[1]: type constrains the accepted value (a string, number, bool, or a complex type), description documents it, default supplies a fallback, sensitive = true keeps the value out of CLI output, and nullable controls whether null is an acceptable value. Terraform v1.10 added one more, ephemeral[2], which makes a value available at runtime while omitting it from state and plan files; it belongs with managing sensitive data. A nested validation block adds custom rules such as an allowed range or a required prefix; that mechanism has its own page, custom condition validation, so here it is enough to know it lives inside the variable block.
Required versus optional
Whether a variable is required comes down to one thing: does it declare a default[1]. A variable with a default is optional, and Terraform uses that value when no source supplies one. A variable with no default is required. In an interactive run Terraform prompts for the value before it produces a plan; in a non-interactive run, such as one started with -input=false or most automation, the missing value is an error and Terraform stops. The figure summarizes that resolution: a value set by any source is used, otherwise the default, otherwise the required-value prompt or error.
Null values and nullable
By default nullable is true, so a caller may assign null. Setting nullable = false[1] makes null an invalid value for that variable, and Terraform rejects any attempt to set it to null. You write nullable only when you want to reject null, since the permissive default already allows it.
Setting values and precedence
A required variable, or one whose default you want to override, takes its value from one of a few sources, and when two sources disagree a fixed precedence decides the winner.
Where a value can come from
Terraform accepts a variable's value from the command line, variable files, and the environment[1]:
-varon the command line:terraform apply -var="region=us-east-1". It is repeatable, and among command-line options the last one to set a given variable wins.-var-fileon the command line:terraform apply -var-file="prod.tfvars", loading a whole file of assignments at once..tfvarsfiles: a file ofname = valueassignments. Which of these load on their own is the next subsection.TF_VAR_environment variables: an environment variableTF_VAR_region=us-east-1[1] sets the input variableregion. This is the common way to feed a secret or a CI value without writing it into a file.- The
default: the fallback declared in thevariableblock, used only when nothing else sets the value.
Which files auto-load
Terraform loads three kinds of file from the working directory with no flag[1]: terraform.tfvars, terraform.tfvars.json, and every file whose name ends in .auto.tfvars or .auto.tfvars.json. Any other name is invisible unless you pass it with -var-file. So terraform.tfvars and prod.auto.tfvars load by themselves, while prod.tfvars loads only via terraform apply -var-file=prod.tfvars. The misconception runs the other way just as often: terraform.tfvars does not need -var-file, it is picked up automatically.
Precedence, highest to lowest
When more than one source sets the same variable, Terraform applies this precedence, from highest to lowest[1]:
-varand-var-fileon the command line, in the order given (later wins).*.auto.tfvarsand*.auto.tfvars.json, processed in lexical filename order.terraform.tfvars.json.terraform.tfvars.TF_VAR_environment variables.- The
defaultin thevariableblock.
Read the ladder in this direction: a command-line -var beats every file, any .tfvars file beats an environment variable, and the default is the last resort. A common trap reverses part of it, claiming a TF_VAR_ value or a terraform.tfvars entry overrides a -var given on the same run. It does not: the command line always wins.
Output values
Outputs are the other half of a module's interface: an output block publishes a value so a parent module can read it, or so an operator can see it after an apply.
Declaring an output
An output block[3] has one required argument, value, set to any valid expression, plus optional arguments such as description, sensitive, depends_on, and precondition:
output "instance_ip" {
value = aws_instance.web.private_ip
description = "Private IP of the app server"
}
A root-module output like this is printed after terraform apply[3] and is available from the terraform output command[4]: plain terraform output prints them all, terraform output instance_ip prints one, and -json or -raw format the result for scripts.
Outputs are how modules expose data
A child module's resources are private to it. The only way a parent reads data a child produced is through an output the child declares[3], addressed as module.<MODULE_NAME>.<OUTPUT_NAME>. Reaching for a child's resource directly, such as module.web.aws_instance.this.id, does not work: the child must first surface it with an output, after which the parent reads module.web.instance_id. The figure traces one value from a child resource up to the command line.
Sensitive outputs hide the console, not the state
Marking an output sensitive = true[3] changes exactly one thing: Terraform prints <sensitive> in place of the value in plan, apply, and terraform output display. It does not encrypt the value or keep it out of state. Terraform stores the values of sensitive outputs in state[3] in plain text, and terraform output -json or terraform output -raw NAME print them unredacted. So sensitive guards against a shoulder-surfer or a leaked CI log, not against state exposure, which is why sensitive state belongs in a secured, access-controlled backend (see managing sensitive data). One related rule follows from the same design: if an output's value references a value Terraform already treats as sensitive, you must mark the output sensitive too, or Terraform reports an Output refers to sensitive values error[5].
How this appears on the exam
This objective is tested less by definitions than by spotting the plausible-but-wrong option. Each trap below is a restatement of a rule established above:
- Referencing a variable. A stem uses the bare name,
region, where the module body needsvar.region. Inside configuration a variable is alwaysvar.<NAME>; the bare name is a syntax error. - Required versus optional. "What happens to a variable with no
defaultwhen nothing sets it?" In an interactive run Terraform prompts; under-input=falseor automation it errors. It never silently becomes null or empty. - Which files auto-load.
terraform.tfvars,terraform.tfvars.json, and*.auto.tfvars(.json)load with no flag;prod.tfvarsloads only with-var-file. The distractor claimsterraform.tfvarsneeds-var-file, or that only*.auto.tfvarsfiles auto-load. - Precedence direction. "A variable is set by both a
-varflag andterraform.tfvars; which applies?" The command line wins. Any answer whereterraform.tfvarsor aTF_VAR_value overrides-varis wrong. - Reading a child module. The parent reads
module.<NAME>.<OUTPUT>, and only declared outputs are visible. "Reference the module's resource directly" is the wrong answer; the module must expose it with anoutputfirst. - Sensitive outputs.
sensitive = trueredacts the console display as<sensitive>, but the value is still in state in plain text andterraform output -json/-rawreveal it. "It is omitted from or encrypted in state" is the distractor.
Variable value sources, by precedence
| Source | How it is set | Auto-loaded | Precedence (1 = wins) |
|---|---|---|---|
| `-var` / `-var-file` | Passed on the CLI; last occurrence wins | No, always explicit | 1 (highest) |
| `*.auto.tfvars(.json)` | Any file with that suffix in the directory | Yes, in lexical order | 2 |
| `terraform.tfvars.json` | That exact filename | Yes | 3 |
| `terraform.tfvars` | That exact filename | Yes | 4 |
| `TF_VAR_<name>` | Environment variable | Yes, from the environment | 5 |
| `default` | `default` in the `variable` block | n/a | 6 (lowest) |
Decision tree
Sharp facts the exam loves — give these one last read before exam day.
Cheat sheet
Sharp facts the exam loves — scan these before test day.
- Variables without default are required
A
variableblock with nodefaultis required; Terraform prompts for its value interactively, or errors in a non-interactive run, when it is not supplied.Trap Assuming a variable without a default silently becomes null or empty.
4 questions test this
- A teammate claims that if you declare `variable "tags" {}` without a `default` and then never supply a value, Terraform will simply treat `var.tags` as an empty or null value when it plans. Which stat
- Every time teammates run `terraform plan` on a shared module, Terraform stops and prompts them to enter a value for `variable "replica_count"`. The team wants the variable to stop prompting and instea
- A CI/CD pipeline runs `terraform plan -input=false` for a configuration that declares `variable "environment" {}` with no default. The pipeline supplies no -var or -var-file flags, no terraform.tfvars
- A developer declares `variable "db_password" {}` with a `type` argument but no `default`, adds no terraform.tfvars file, and runs `terraform plan` interactively in a local terminal with no `-var` flag
- Variable type and nullable
typeconstrains the accepted value,defaultsupplies a fallback, andnullable = falseforbids a null value (the default isnullable = true).4 questions test this
- An engineer declares a variable with three arguments: `type = list(string)`, `default = []`, and `nullable = false`. A teammate asks how these three arguments divide responsibility for the variable's
- A variable block for `labels` sets `type = map(string)` and a `default`, but omits the `nullable` argument entirely. A module consumer then explicitly assigns `labels = null`. Given that nullable is n
- Every time teammates run `terraform plan` on a shared module, Terraform stops and prompts them to enter a value for `variable "replica_count"`. The team wants the variable to stop prompting and instea
- In a module, an engineer writes a variable block for `image_id` with `type = string` and `nullable = false`, and gives it no default. A consumer of the module explicitly passes `image_id = null`. What
- Access variables with var.
Inside configuration a variable's value is accessed as
var.<NAME>, never by the bare variable name.Trap Referencing a variable as
vpc_cidrsinstead ofvar.vpc_cidrs.4 questions test this
- An engineer's configuration sets a resource argument to `vpc_cidrs` - the bare name of a declared input variable - and `terraform validate` fails because Terraform reads `vpc_cidrs` as a reference to
- While refactoring a module, an engineer keeps an input variable named `bucket_name` and, in a `locals` block, adds a local value also named `bucket_name` that appends a random suffix to it. One resour
- A configuration declares `variable "region" {}`. Inside an `aws_instance` resource block, an engineer needs one of the resource arguments to use the value that was supplied for that input variable. Wh
- A module declares `variable "network"` using an object type that includes an attribute named `subnet_id`. Inside a resource block, the engineer needs the `subnet_id` field of the value supplied for th
- Which tfvars auto-load
Terraform automatically loads
terraform.tfvars,terraform.tfvars.json, and any*.auto.tfvars/*.auto.tfvars.jsonfiles from the working directory with no extra flags; other.tfvarsfiles must be passed explicitly with-var-file.Trap Thinking
terraform.tfvarsis ignored unless passed with-var-file, or that only*.auto.tfvarsfiles auto-load.8 questions test this
- A `region` variable is assigned `us-east-1` in a `terraform.tfvars` file in the working directory. A platform engineer then runs `terraform apply -var="region=us-west-2"` from that same directory. Whi
- A team keeps default override values in a file and wants Terraform to load it automatically on every plan and apply, without anyone remembering to pass `-var-file`, and the file must not be named `ter
- A CI system writes variable values into a file named `terraform.tfvars.json` in the working directory. A teammate claims Terraform auto-loads only HCL `.tfvars` files, so this JSON file must be passed
- The variable `env` is assigned "staging" in `terraform.tfvars`, "testing" in `terraform.tfvars.json`, and "production" in `prod.auto.tfvars`, all in the same working directory. No `-var` flag is used
- An engineer has exported the environment variable `TF_VAR_environment=staging` in their shell, while the working directory's `terraform.tfvars` file sets `environment = "production"`. They run a bare
- A working directory contains a `terraform.tfvars` file that sets `instance_count = 2` and a `prod.auto.tfvars` file that sets `instance_count = 5`. An engineer runs a bare `terraform plan` with no `-v
- A working directory contains four files: `terraform.tfvars`, `production.tfvars`, `network.auto.tfvars`, and `terraform.tfvars.json`. An engineer runs `terraform apply` with no additional flags. Which
- An engineer created a file named `common.tfvars` in the working directory, expecting `terraform apply` to pick up its shared values automatically, but the values were not applied to the run. Why were
- TF_VAR_ environment variables
An environment variable named
TF_VAR_<name>sets the value of the input variable<name>.6 questions test this
- A variable `instance_count` is set to 2 in `terraform.tfvars`, the shell also has `TF_VAR_instance_count=3` exported, and an engineer runs `terraform apply -var="instance_count=5"`. All three sources
- An input variable `log_level` declares `default = "info"` and no .tfvars file sets it. A developer exports `TF_VAR_log_level=debug` in the shell and runs `terraform apply` with no `-var` flag. Which v
- In a CI pipeline that cannot write .tfvars files to disk, an engineer must supply a list value for the input variable `subnet_ids` using only an exported environment variable before `terraform apply`.
- An engineer has exported the environment variable `TF_VAR_environment=staging` in their shell, while the working directory's `terraform.tfvars` file sets `environment = "production"`. They run a bare
- A platform engineer is preparing to run `terraform apply` in a working directory that has no `-var` or `-var-file` flags and no `*.auto.tfvars` files. The shell has `TF_VAR_region=us-east-1` exported,
- An engineer needs to set the value of an input variable named `region` for a single run without editing any .tfvars file and without using the `-var` flag, by exporting a shell environment variable be
- Variable precedence order
When a variable is set in multiple places, precedence from highest to lowest is:
-var/-var-file(command line, last one wins),*.auto.tfvars(processed in lexical filename order),terraform.tfvars.json,terraform.tfvars,TF_VAR_environment variables, then thedefault.Trap Believing environment variables or
terraform.tfvarsoverride a command-line-varvalue.8 questions test this
- A `region` variable is assigned `us-east-1` in a `terraform.tfvars` file in the working directory. A platform engineer then runs `terraform apply -var="region=us-west-2"` from that same directory. Whi
- An engineer runs `terraform apply -var-file=base.tfvars -var-file=override.tfvars`, and both files assign a value to the variable `replicas`. Neither file is auto-loaded by name. Which file's value fo
- A variable `instance_count` is set to 2 in `terraform.tfvars`, the shell also has `TF_VAR_instance_count=3` exported, and an engineer runs `terraform apply -var="instance_count=5"`. All three sources
- An input variable `log_level` declares `default = "info"` and no .tfvars file sets it. A developer exports `TF_VAR_log_level=debug` in the shell and runs `terraform apply` with no `-var` flag. Which v
- The variable `env` is assigned "staging" in `terraform.tfvars`, "testing" in `terraform.tfvars.json`, and "production" in `prod.auto.tfvars`, all in the same working directory. No `-var` flag is used
- An engineer has exported the environment variable `TF_VAR_environment=staging` in their shell, while the working directory's `terraform.tfvars` file sets `environment = "production"`. They run a bare
- A platform engineer is preparing to run `terraform apply` in a working directory that has no `-var` or `-var-file` flags and no `*.auto.tfvars` files. The shell has `TF_VAR_region=us-east-1` exported,
- A working directory contains a `terraform.tfvars` file that sets `instance_count = 2` and a `prod.auto.tfvars` file that sets `instance_count = 5`. An engineer runs a bare `terraform plan` with no `-v
- Output block value argument
An
outputblock exposes data through its requiredvalueargument; root-module outputs are printed after apply and by theterraform outputcommand.8 questions test this
- A root configuration calls a child module labeled `network`, and that child declares an output named `subnet_id`. A teammate runs `terraform output` in the root directory expecting to see `subnet_id`,
- An engineer needs the private subnet ID created inside a child module named `network` and writes `module.network.aws_subnet.private.id` in the root configuration, but Terraform reports that the refere
- An engineer provisions an application load balancer whose DNS name is generated by the provider and is only known after creation. They want the root module to surface that DNS name so teammates can re
- An engineer wants a root `output` named `connection_string` whose value combines an `aws_db_instance` resource's `address` attribute with a fixed port suffix using string interpolation. Is such a comb
- After a successful `terraform apply`, an automation script needs the value of a single root output named `alb_dns_name` — not the full list of outputs — read back from the current state. Which command
- A teammate cleared their terminal and can no longer see the output values that `terraform apply` printed earlier. They want to redisplay those root module outputs without changing any infrastructure o
- A platform engineer adds an `output` block named `db_endpoint` to the root module and runs `terraform validate`, which fails with an error reporting a missing required argument. Which argument must ev
- After defining several `output` blocks in the root module of a configuration, an engineer runs `terraform apply` and approves the change. Without running any additional command afterward, where do the
- Accessing child module outputs
A parent module reads a child module's output as
module.<MODULE_NAME>.<OUTPUT_NAME>; only declared outputs are exposed, not the child's internal resources.Trap Attempting to reference a child module's resource directly instead of through a declared output.
2 questions test this
- A root configuration calls a child module labeled `network`, and that child declares an output named `subnet_id`. A teammate runs `terraform output` in the root directory expecting to see `subnet_id`,
- An engineer needs the private subnet ID created inside a child module named `network` and writes `module.network.aws_subnet.private.id` in the root configuration, but Terraform reports that the refere
- Sensitive output behavior
sensitive = trueon an output redacts it as<sensitive>in CLI output but the value is still stored in state, andterraform output -json/-rawreveal it.Trap Assuming a sensitive output is omitted from or encrypted in the state file.
4 questions test this
- An engineer adds `sensitive = true` to a root `output` block that exposes a generated database password and then runs `terraform apply`. What does Terraform display for that output at the end of the a
- A CI pipeline needs the plaintext value of a root output declared with `sensitive = true` so it can pass the value to a downstream step. Running `terraform output db_password` returns a redacted resul
- A security reviewer asks whether adding `sensitive = true` to an output that exposes an API token keeps that token out of the Terraform state file, or encrypts it there. For a configuration using the
- An engineer declares an input variable `db_password` with `sensitive = true`, then adds a root-module `output` named `database_password` whose `value` is `var.db_password`, but does not set `sensitive