All guides
Practice now
D2 · Terraform workflow

CLI commands: init, plan, apply, destroy, and more

Mastering the flags of each CLI command is essential for the exam. This guide covers each command with its most important options and when to use them.

terraform init

Initializes the working directory. It must be run before any other command, after creating a new configuration or changing /.

FlagDescriptionWhen to use it
-upgradeUpdates providers to the highest range allowed by the constraintsWhen you want to use newer provider versions
-reconfigureReconfigures the backend, ignoring the previously saved stateWhen you change the backend configuration
-migrate-stateMoves the existing state to the newly configured backendWhen switching from a local to a remote backend (or vice versa)
-backend-configPasses partial backend configuration as an argument or fileTo avoid hardcoding credentials in the backend {} block
-backend=falseSkips backend initializationIn modules that don't have their own backend
-get=falseSkips downloading modulesWhen you only want to reinstall providers
# First initialization
terraform init

# Update providers to newer versions
terraform init -upgrade

# Migrate state from local to S3
terraform init -migrate-state

# Pass backend config without hardcoding it in .tf
terraform init -backend-config="bucket=my-tfstate" -backend-config="region=us-east-1"
terraform init -backend-config=backend.hcl  # from a file

terraform plan

Generates and shows the without making real changes. It's the most commonly used command day to day.

FlagDescription
-out=<file>Saves the plan to a binary file to apply it exactly later with terraform apply <file>
-target=<resource>Limits the plan to a specific resource (e.g.: -target=aws_vpc.main). Use with caution.
-destroyGenerates a destruction plan for all resources (equivalent to terraform destroy but plan-only)
-refresh-onlyOnly refreshes state against reality without planning config changes (detects )
-var="key=value"Defines an inline variable. Can be repeated for multiple variables.
-var-file=<file>Loads variables from an additional .tfvars file
-refresh=falseSkips refreshing state (faster but may not detect external manual changes)
-parallelism=NNumber of concurrent operations (default: 10)
# Normal plan
terraform plan

# Save the plan (recommended in CI/CD pipelines)
terraform plan -out=tfplan.binary

# Plan with inline variable
terraform plan -var="environment=prod" -var="instance_type=t3.large"

# Plan with a variables file
terraform plan -var-file=prod.tfvars

# Refresh-only plan (detect drift)
terraform plan -refresh-only

# Destroy plan
terraform plan -destroy

💡 -target in production

The -target flag is useful in emergencies but can leave the state inconsistent. HashiCorp recommends not using it routinely. If you need to apply only part of the config, consider structuring it into separate modules.

terraform apply and destroy

terraform apply

# Applies by generating a new plan (asks for confirmation)
terraform apply

# Applies without confirmation (CI/CD)
terraform apply -auto-approve

# Applies a saved plan (no confirmation prompt)
terraform apply tfplan.binary

# Applies only a specific resource
terraform apply -target=aws_vpc.main

# With variables
terraform apply -var="env=prod"
terraform apply -var-file=prod.tfvars

terraform destroy

# Destroys all resources (asks for confirmation)
terraform destroy

# Without confirmation (DANGEROUS in prod)
terraform destroy -auto-approve

# Destroys only one resource
terraform destroy -target=aws_instance.web

# Equivalent alternative:
terraform apply -destroy
terraform apply -destroy -auto-approve

⚠️ terraform destroy is irreversible

Destroy removes the real resources in the cloud. Before destroying in production, check the plan with terraform plan -destroy and consider using prevent_destroy = true in the lifecycle of critical resources.

terraform fmt and validate

CommandWhat it doesImportant flags
terraform fmtReformats the .tf files in the current directory to the canonical HCL style (2 spaces, aligned =)-recursive: also processes subdirectories | -check: only checks, doesn't modify (useful in CI) | -diff: shows the diff without applying it
terraform validateVerifies that the configuration is syntactically valid and internally consistent (without connecting to APIs)-json: JSON output for CI/CD
# Format all .tf files in the current directory
terraform fmt

# Format recursively (includes subdirectories / modules)
terraform fmt -recursive

# Only check formatting without modifying (for CI)
terraform fmt -check
terraform fmt -check -recursive

# Validate syntax and internal consistency
terraform validate

# Recommended combo in pre-commit hooks:
terraform fmt -check && terraform validate

💡 validate vs. plan

terraform validate checks syntax and internal references without connecting to the cloud APIs. It does not detect permission errors or invalid resource names. terraform plan does connect to the APIs and detects those errors.

output, show, graph, and more

terraform output

Shows the values of the from the current state.

terraform output                    # all outputs
terraform output vpc_id             # specific output
terraform output -json              # all in JSON
terraform output -json vpc_id       # one in JSON

terraform show

Shows the or the contents of a plan file in a human-readable format.

terraform show                      # shows the current state
terraform show tfplan.binary        # shows the saved plan
terraform show -json                # state in JSON

terraform graph

Generates the dependency graph in DOT format (viewable with Graphviz).

terraform graph                     # generates DOT to stdout
terraform graph | dot -Tsvg > infra.svg  # visualize

terraform force-unlock

Manually releases a state lock that got stuck (e.g.: an interrupted apply). Requires the lock ID.

terraform force-unlock LOCK_ID

terraform login / logout

Authenticates with HCP Terraform (app.terraform.io) to access remote workspaces.

terraform login                     # opens a browser to authenticate
terraform logout                    # removes the local token

terraform console

Interactive REPL for evaluating HCL expressions. Useful for debugging functions and references.

terraform console
> max(3, 5, 8)
8
> jsonencode({a = "b"})
"{\"a\":\"b\"}"

Did you get this topic?

Test what you just learned

A team uses a CI/CD pipeline with two stages: the first generates the plan and the second applies it. Which command sequence guarantees that exactly the reviewed plan is the one applied?

Ready to test "CLI Commands: init, plan, apply, destroy and More"?

Put what you learned to the test with original Terraform Associate exam questions.

Start Terraform Associate mock exam

Unlimited mock exams with the Pro plan

Log in to track your progress.