terraform planPreview what Terraform will change
terraform plan compares your configuration with the state and the real infrastructure, and shows exactly what apply would create (+), change in place (~), replace (-/+) or destroy (-). It changes nothing, so it's the step every change should be reviewed at.
terraform plan [-out=FILE] [-var 'k=v'] [-var-file=FILE] [-target=ADDR] [-replace=ADDR] [-refresh-only] [-destroy] [-detailed-exitcode]Before the first apply in dev, review what Terraform intends to build: one EC2 instance, an S3 bucket and a random suffix.
terraformThe Terraform CLI.
plan takes the state lock, then loads the configuration and evaluates variables, locals and module calls into a dependency graph of resources. It reads the last state (resource addresses, IDs, attributes). Unless -refresh=false, it asks each provider (a plugin process Terraform talks to over gRPC) to ReadResource for every managed object: the AWS provider calls Describe/Get APIs, so changes made in the console show up as drift. Then for each resource it calls PlanResourceChange with the configured values and the current state; the provider returns the proposed new state, marks unknown values as (known after apply), and says which changed attributes force replacement. Terraform core assembles these into create, update, replace, delete and no-op actions in dependency order, prints the diff, optionally writes it with -out, and releases the lock. Nothing in the cloud is modified; the only writes are refreshed values kept in the plan.
Plan merges three views: your code, the last known state and the real cloud, and lets each provider decide what can change in place.
Before reading anything, Terraform locks the state (an S3 .tflock object or a DynamoDB item) so nobody else can apply while this plan is computed.
-out=FILESave the plan; apply FILE runs exactly this-var 'k=v' / -var-file=FSet input variables-target=ADDRPlan only this resource and its dependencies (exceptional use)-replace=ADDRForce a resource to be destroyed and recreated-refresh-onlyOnly show drift and update state to match reality-refresh=falseSkip reading real infrastructure (faster, riskier)-destroyPlan the destruction of everything in state-detailed-exitcode0 no changes, 1 error, 2 changes-lock-timeout=60sWait for a busy state lock instead of failing-no-color / -jsonPlain text for logs / machine-readable outputReviewing only the 'Plan: X to add, Y to change, Z to destroy' lineA one-line code change can show as 1 change but hide a '# forces replacement' that wipes a database.
Search the plan for 'must be replaced' and 'destroy' before approvingRunning plan, then apply without the plan fileapply re-plans; if code, variables or the cloud changed in between, it may do something you didn't review.
terraform plan -out=tfplan, review, then terraform apply tfplanUsing -target routinely to 'just deploy my part'It skips dependencies and leaves state partially converged; Terraform itself warns it's for exceptional cases.
Split state into smaller root modules if components deploy independentlyIgnoring 'Objects have changed outside of Terraform'The plan will silently undo someone's hotfix (or keep a dangerous manual change if you add ignore_changes blindly).
Decide per change: codify it, or let Terraform revert itTry these on a Linux machine of your own. Each task has a hint and a solution.
In ~/infra (after terraform init), plan the prod environment with prod.tfvars, save it as prod.tfplan, and fail on missing variables instead of prompting.
Read this plan line and say what will happen: ' # aws_db_instance.main must be replaced' with '~ engine_version = "15.7" -> "16.3" # forces replacement'.
Write a shell snippet for a nightly job that prints DRIFT when plan finds changes and exits non-zero on errors. Try it in ~/infra after apply: add an SSH rule to the web security group with the aws CLI and run it again.
terraform planPreview what Terraform will change
terraform plan compares your configuration with the state and the real infrastructure, and shows exactly what apply would create (+), change in place (~), replace (-/+) or destroy (-). It changes nothing, so it's the step every change should be reviewed at.
terraform plan [-out=FILE] [-var 'k=v'] [-var-file=FILE] [-target=ADDR] [-replace=ADDR] [-refresh-only] [-destroy] [-detailed-exitcode]Before the first apply in dev, review what Terraform intends to build: one EC2 instance, an S3 bucket and a random suffix.
terraformThe Terraform CLI.
plan takes the state lock, then loads the configuration and evaluates variables, locals and module calls into a dependency graph of resources. It reads the last state (resource addresses, IDs, attributes). Unless -refresh=false, it asks each provider (a plugin process Terraform talks to over gRPC) to ReadResource for every managed object: the AWS provider calls Describe/Get APIs, so changes made in the console show up as drift. Then for each resource it calls PlanResourceChange with the configured values and the current state; the provider returns the proposed new state, marks unknown values as (known after apply), and says which changed attributes force replacement. Terraform core assembles these into create, update, replace, delete and no-op actions in dependency order, prints the diff, optionally writes it with -out, and releases the lock. Nothing in the cloud is modified; the only writes are refreshed values kept in the plan.
Plan merges three views: your code, the last known state and the real cloud, and lets each provider decide what can change in place.
Before reading anything, Terraform locks the state (an S3 .tflock object or a DynamoDB item) so nobody else can apply while this plan is computed.
-out=FILESave the plan; apply FILE runs exactly this-var 'k=v' / -var-file=FSet input variables-target=ADDRPlan only this resource and its dependencies (exceptional use)-replace=ADDRForce a resource to be destroyed and recreated-refresh-onlyOnly show drift and update state to match reality-refresh=falseSkip reading real infrastructure (faster, riskier)-destroyPlan the destruction of everything in state-detailed-exitcode0 no changes, 1 error, 2 changes-lock-timeout=60sWait for a busy state lock instead of failing-no-color / -jsonPlain text for logs / machine-readable outputReviewing only the 'Plan: X to add, Y to change, Z to destroy' lineA one-line code change can show as 1 change but hide a '# forces replacement' that wipes a database.
Search the plan for 'must be replaced' and 'destroy' before approvingRunning plan, then apply without the plan fileapply re-plans; if code, variables or the cloud changed in between, it may do something you didn't review.
terraform plan -out=tfplan, review, then terraform apply tfplanUsing -target routinely to 'just deploy my part'It skips dependencies and leaves state partially converged; Terraform itself warns it's for exceptional cases.
Split state into smaller root modules if components deploy independentlyIgnoring 'Objects have changed outside of Terraform'The plan will silently undo someone's hotfix (or keep a dangerous manual change if you add ignore_changes blindly).
Decide per change: codify it, or let Terraform revert itTry these on a Linux machine of your own. Each task has a hint and a solution.
In ~/infra (after terraform init), plan the prod environment with prod.tfvars, save it as prod.tfplan, and fail on missing variables instead of prompting.
Read this plan line and say what will happen: ' # aws_db_instance.main must be replaced' with '~ engine_version = "15.7" -> "16.3" # forces replacement'.
Write a shell snippet for a nightly job that prints DRIFT when plan finds changes and exits non-zero on errors. Try it in ~/infra after apply: add an SSH rule to the web security group with the aws CLI and run it again.