Skip to main content

Terraform Plan

The terraform plan command shows you exactly what Terraform will create, change, or destroy before it does anything. It reads your configuration files, compares them to the current state file, and prints a diff — giving you a safe preview before you apply.

What Is Terraform Plan?

Terraform plan is the review step before any infrastructure change. It reads your .tf files, looks at the current state file, checks what actually exists in the cloud, and prints a precise diff showing what will be created, modified, or destroyed. Nothing changes when you run plan — it is entirely read-only.

At Razorpay, no infrastructure change gets applied without a plan output reviewed in a pull request. Plan is the safety check that catches mistakes before they cost money or cause downtime.

Running Terraform Plan

Bash
# Basic plan — shows what will change
terraform plan
# Save the plan to a file (recommended for CI/CD)
terraform plan -out=tfplan
# Apply exactly the saved plan later (no re-evaluation)
terraform apply tfplan
# Plan for a specific variable file
terraform plan -var-file=prod.tfvars
# Plan targeting a specific resource only
terraform plan -target=aws_s3_bucket.order_images

Reading Plan Output

◈ DIAGRAM
Terraform will perform the following actions:
# aws_s3_bucket.order_images will be created
+ resource "aws_s3_bucket" "order_images" { # + means CREATE
+ bucket = "swiggy-order-images-prod"
+ region = (known after apply) # only known once created
}
# aws_instance.web will be updated in-place
~ resource "aws_instance" "web" { # ~ means UPDATE
~ instance_type = "t3.small" -> "t3.medium" # old -> new
id = "i-0a1b2c3d4e5f"
}
# aws_db_instance.payments must be replaced
-/+ resource "aws_db_instance" "payments" { # -/+ means DESTROY then CREATE
~ engine_version = "13.4" -> "14.0" # forces replacement
- identifier = "payments-prod" # - means attribute removed
}
# aws_s3_bucket.old_bucket will be destroyed
- resource "aws_s3_bucket" "old_bucket" { # - means DESTROY
- bucket = "swiggy-old-data"
}
Plan: 1 to add, 1 to change, 1 to destroy.

Plan Symbol Reference

Symbol Meaning Risk
+ Resource will be created Low — new resource
~ Resource will be updated in-place Low — no recreation
-/+ Resource will be destroyed and recreated High — downtime possible
- Resource will be destroyed High — data loss risk
<= Data source will be read None — read-only

Saving and Using Plan Files

Bash
# In CI/CD — save plan during PR check
terraform plan -out=tfplan.binary
# Show the saved plan in human-readable form
terraform show tfplan.binary
# Show the saved plan as JSON (for cost estimation tools)
terraform show -json tfplan.binary > tfplan.json
# Apply exactly what was planned — no re-evaluation, no surprises
terraform apply tfplan.binary
Tip

Always use -out in CI/CD pipelines. Without it, the apply stage re-evaluates the plan, which can differ from what was reviewed if infrastructure changed between the PR check and the merge.

What Plan Does NOT Show

Bash
# Plan does not detect changes made outside Terraform by default
# If someone changed an EC2 instance type in the console, plan may not show it
# Use -refresh=true (default) or apply -refresh-only to sync state first
terraform plan -refresh=true

Troubleshooting Plan

Error Cause Fix
Error: No configuration files Running plan in wrong directory cd to directory containing .tf files
Error: Backend configuration changed Backend block modified Run terraform init -reconfigure
Error acquiring the state lock Another apply running Wait or run terraform force-unlock <ID>
Plan shows -/+ unexpectedly Argument forces replacement Check provider docs — some changes always recreate
Common Mistake

Seeing a -/+ replace for a database and applying without reading why. Some changes — like changing an RDS engine version — force Terraform to destroy and recreate the instance. Always read the reason shown in parentheses after the replacement symbol.

Frequently Asked Questions

Can terraform plan be wrong about what will actually happen on apply?

Yes — plan is a best-effort prediction based on the current state and provider API responses at plan time, but if real infrastructure changes between plan and apply (someone else applies a change, or a cloud provider modifies a computed value), the apply can diverge from what plan showed. Some resource attributes are also only 'known after apply' (like an auto-generated ID), which plan shows as `(known after apply)` rather than a concrete value, since the provider can't predict it in advance.

What's a best practice for using terraform plan safely in a team workflow?

Save the plan to a file with `terraform plan -out=tfplan`, have it reviewed (in a PR or by a teammate), then apply that exact saved file rather than re-running plan implicitly at apply time — this guarantees what was reviewed is what gets executed, closing the gap where state could shift between review and execution. Never treat a plan review as optional just because the diff 'looks small'; small diffs on a security group or IAM policy can still be high-impact.