skip to content

Core Commands and Saved Plans

init, plan, apply, destroy is the loop I will run thousands of times, and saving a plan to a file is what makes the apply match what was reviewed. Interviewers check that I never approve one diff and apply another.

part ofTerraformoverview, primer and where to startread it →
on this pageshow

questions

6

In Terraform, what do `terraform plan` and `terraform apply` each do, and what does the `-auto-approve` flag change about `terraform apply`?

level: juniorimportance: must knowfreq 85%

answer

  1. one command looks, one command acts
  2. the prompt between them
  3. apply computes its own diff
  4. only the word yes approves
  5. -auto-approve removes the human

basics

~10 s

terraform plan computes and prints the changes needed to make real infrastructure match the configuration, without changing anything. terraform apply makes those changes, pausing for an interactive confirmation first; -auto-approve skips that confirmation prompt.

solid answer

~40 s

`terraform plan` is the read-only step: it reads your configuration, the recorded state and the real objects, then prints the diff — what it would create, update, replace or destroy — and exits without touching anything. `terraform apply` does the work. Run bare, it computes its **own fresh plan**, shows it, and stops at a prompt where you must type the literal word `yes`; only then does it call the provider APIs. `-auto-approve` removes that prompt, so apply goes straight from planning to changing production. It is what you use in automation, but it means nobody looked at the diff that was actually applied — which is why pipelines normally pair it with an approval gate or, better, apply a plan that was saved to a file and reviewed.

code

bash · 8 lines
bash
terraform init
terraform fmt -recursive
terraform validate
terraform plan
terraform apply

# non-interactive form used by pipelines
terraform apply -input=false -auto-approve

go deeper

for a junior

Be ready to state plainly that plan only shows the proposed changes while apply makes them, and that apply stops for a confirmation you must answer with the word yes.

for a middle

Explain that a bare apply runs its own planning phase rather than replaying an earlier plan, and describe what the action symbols and the add/change/destroy summary line are telling you.

for a senior

Show the production judgment: where -auto-approve is legitimate, what compensating control replaces the lost human check, and how you keep the reviewed diff and the applied diff the same artefact.

for a principal

Own the policy question — who is allowed to approve an apply, whether approval lives in the terminal or the pipeline, and what evidence of the approved change your organisation needs to keep afterwards.

## The two commands Terraform works from three inputs: the configuration you wrote in `.tf` files, the state file recording which real objects it already manages, and the real infrastructure as reported by provider APIs. Every core command is some combination of reading those three and reconciling them. `terraform plan` answers one question: what would have to change so that reality matches the configuration? It produces a diff and exits. Nothing is created, updated or destroyed. That safety is the whole point — plan is the command you can run on anything, at any time, including someone else's repository, to find out what a change would do before it does it. `terraform apply` executes the changes. It walks the dependency graph, calls the provider APIs in order, and records the results in state as it goes. ## Reading the diff A plan prints one block per changing object, prefixed by an action symbol: ``` + create ~ update in place - destroy -/+ destroy and then create replacement ``` and ends with a summary line like `Plan: 2 to add, 1 to change, 0 to destroy.` Attributes the provider will only know after the call succeeds are printed as `(known after apply)`. The two lines to actually read are the destroy count and every `-/+` — those are the ones that take an outage. ## What a bare apply really does The common misconception is that `terraform apply` applies the plan you looked at five minutes ago. It does not. Without a plan file argument it runs the planning phase again from scratch, prints the result, and asks: ``` Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: ``` The check is exact: `y`, `Y`, `Yes` and a bare Enter all cancel the run. This deliberate friction exists because the diff on screen was computed seconds ago and is the one about to be executed — the prompt is the review. ## `-auto-approve` `terraform apply -auto-approve` skips that question. `terraform destroy -auto-approve` does the same for a teardown. There is no partial form: it is on or off. In a pipeline the prompt is not merely inconvenient, it is unanswerable — there is no terminal to type into. That is the legitimate use. The cost is that the reviewed diff and the applied diff are two different computations, separated by however long the approval took; anything that changed in between (a merged pull request, a console edit, a variable default) silently lands in the applied one. Two related flags matter in automation. `-input=false` tells Terraform never to prompt for anything, including missing variable values — instead of hanging on a hidden question, the run fails fast with a clear error. And a plan saved with `-out` and applied as `terraform apply tfplan` never prompts at all, because the changes are already fixed in the file, so `-auto-approve` is not needed there. ## Where the other core commands sit Around this pair sit the rest of the loop. `terraform init` prepares the directory and must run first. `terraform fmt` rewrites files to canonical formatting. `terraform validate` checks the configuration is internally consistent without contacting any API. `terraform destroy` is the inverse of apply. In practice the day-to-day sequence is: write code, `fmt`, `validate`, `plan`, read the diff properly, `apply`. ## What interviewers are checking They want to hear that plan is safe and apply is not, that apply re-plans rather than replaying what you saw, and that `-auto-approve` is a tool for machines with a compensating control, not a shortcut for humans who find the prompt annoying. A candidate who says "I always use `-auto-approve` because it saves a step" has told the interviewer they approve diffs they have not read.

  • If I run `terraform plan`, read the diff, then run `terraform apply` five minutes later, is that the same diff?
    Not necessarily. A bare `terraform apply` computes a completely new plan; it does not replay the earlier one. If state, the real infrastructure or the configuration moved in between, the diff you approve at the prompt may differ from the one you read. The way to guarantee they match is `terraform plan -out=tfplan` followed by `terraform apply tfplan`.
  • What does `-input=false` do, and does it replace `-auto-approve`?
    `-input=false` tells Terraform never to ask an interactive question — a missing variable becomes an error instead of a prompt. It does not approve anything: an apply run with `-input=false` alone fails rather than proceeding. In automation you need `-input=false` for the safety and either `-auto-approve` or a saved plan file for the approval.
  • Is `terraform plan` completely side-effect free?
    It makes no changes to your infrastructure, which is what matters. It does read: it needs valid provider credentials to query the real objects, and by default it takes the state lock for the duration so a concurrent run cannot interleave. So it is safe, but it is not free of credentials or of contention with other runs.

saying these in an interview costs you the question

  • Says apply executes the plan you reviewed earlier
  • Thinks terraform plan writes changes to infrastructure
  • Believes -auto-approve just makes apply run faster
  • Claims typing y at the prompt approves the run
  • Uses -auto-approve interactively as a default habit

context

open as a page

Why would a team run `terraform plan -out=tfplan` and later `terraform apply tfplan` instead of just running `terraform apply`?

level: middleimportance: must knowfreq 65%

basics

~20 s

So the changes that get applied are exactly the changes that were reviewed. A bare terraform apply computes a brand-new plan at apply time; applying a saved plan file replays the recorded decisions instead, with no re-planning and no approval prompt.

open as a page

In Terraform, how does running `terraform destroy` differ from deleting a resource block from the configuration and running `terraform apply`?

level: middleimportance: should knowfreq 50%

basics

~20 s

terraform destroy proposes deleting everything this configuration currently manages, leaving the code untouched, so a later apply recreates it. Deleting a resource block changes the desired state permanently, so the next apply removes just that one object.

open as a page

What does `terraform init` actually do, and what ends up inside the `.terraform` directory after it runs?

level: middleimportance: should knowfreq 70%

basics

~20 s

terraform init prepares a working directory: it wires up the backend, installs the providers the configuration requires, and fetches remote modules. Plugins land in .terraform/providers and module copies in .terraform/modules, while .terraform.lock.hcl is written beside your code.

open as a page

What does the plan file produced by `terraform plan -out=tfplan` actually contain, and why does that make it sensitive?

level: seniorimportance: should knowfreq 40%

basics

~20 s

A saved plan is an opaque binary archive holding the configuration, a snapshot of prior state and every planned attribute value — including values marked sensitive, which are only masked in the printed output, not removed from the file. Protect it exactly like state.

open as a page

What does `terraform plan -detailed-exitcode` return, and how would you use it in a script?

level: middleimportance: nice to knowfreq 32%

basics

~20 s

With -detailed-exitcode, terraform plan exits 0 when there are no changes, 1 on error, and 2 when the plan succeeded and changes are pending. Scripts use it to tell an empty diff apart from a real one without parsing output.

open as a page