📋 Quick Steps
Decode any Terraform plan in seconds by filtering for what actually matters.
terraform plan -no-color | grep -E '(\-\/\+|~|\+)'
# 2. See ONLY what's being destroyed:
terraform plan -no-color | grep -B2 -A2 '\-'
# 3. Filter out the noise (tags, metadata):
terraform plan -no-color | grep -vE '(tags|labels|metadata|\s+id:)' | head -50
You've been there. You run terraform plan and 200 lines of cryptic symbols scroll past. You see a ~ next to something called aws_instance.web_server. There's a + somewhere. Maybe a -? You squint, pretend to understand, and hit terraform apply while whispering a silent prayer to the cloud gods.
Let's stop the charade. That plan isn't speaking in riddles—it's screaming warnings in a language we've been too lazy to learn. Your infrastructure is trying to tell you exactly what it's about to do. Time to start listening.
TL;DR: Your Terraplan Cheat Sheet
- +/-/~ aren't math symbols—they're creation, destruction, and in-place updates
- -/+ together means "recreate" (downtime alert!)
- Most of that output is noise (tags, metadata)—filter it out immediately
The Terraform Rosetta Stone: Symbol Translation
Terraform speaks in three primary symbols. Master these and you're 80% there.
+ create: Something new. Usually safe, unless it's a duplicate of something being destroyed (see below). Example: + aws_security_group.allow_ssh means you're adding a new firewall rule.
- destroy: Something being deleted. Your heart should skip a beat. Example: - aws_db_instance.production means you're about to delete your production database. Probably bad.
~ update in-place: A change that won't recreate the resource. Usually safe. Example: ~ aws_instance.web_server.tags.Name means you're just renaming something.
The Danger Zone: Spotting -/+ (Recreation)
This is where teams get burned. When you see -/+ next to each other, Terraform is saying: "I must DESTROY this and CREATE a new one." This means potential downtime, IP changes, and broken dependencies.
Example:
-/+ aws_instance.app_server (replace)
Translation: "Your app server will be terminated and a new one spun up. Sessions will be lost. Hope you have good backups."
Common triggers: Changing AMI IDs, instance type (t2.small → t2.medium), or certain network attributes. Always check the "forces replacement" note that follows.
Filtering the Noise: 90% of That Output Is Garbage
The default plan output shows every attribute change, including tags, metadata, and computed IDs. You don't care that arn changed—it's computed. You care about intentional changes.
Step 1: Strip colors and grep for action symbols
terraform plan -no-color | grep -E '(\\-\\/\\+|~|\\+)'
This shows only lines with changes, skipping the endless attribute listings.
Step 2: Isolate destructions
terraform plan -no-color | grep -B2 -A2 '\\-'
Show destructions with 2 lines of context before and after. The context often reveals WHY it's being destroyed.
Configuration Drift vs. Intentional Changes
Sometimes Terraform wants to change things you didn't touch. This is configuration drift—someone or something changed infrastructure outside of Terraform.
Spotting drift: Look for updates (~) to resources you didn't modify in your code. Common culprits: auto-scaling groups adjusting sizes, security groups getting extra rules manually added in AWS console.
What to do: If it's expected drift (auto-scaling), you might ignore it. If it's unexpected (someone manually changed production), investigate immediately. Use terraform refresh cautiously to sync state before planning.
Building Your Team's Custom Filter
Create a bash alias or script that filters for YOUR team's specific concerns. Here's a starter:
grep -vE "(tags\\.|labels\\.|metadata|\\s+id:|arn:|\\s+# )" | \
grep -B1 -A1 -E "(\\-\\/\\+|~|\\+|\\-)"'
This removes tag/metadata noise, shows only change lines with context, and makes plans readable in under 10 lines.
Pro Tips from Someone Who's Been Burned
🔍 Always pipe to a file: terraform plan -no-color > plan.txt then review with your filters. Prevents scrolling disasters.
🚨 Create a "destruction checklist": For each resource type, know what destruction means. Database = data loss. Load balancer = downtime. S3 bucket = bye-bye files.
📊 Use -target strategically but cautiously: terraform plan -target=aws_instance.web_server isolates changes to one resource. Great for debugging, terrible for understanding dependencies.
🤖 Automate the scary stuff: If you see -/+ in your CI/CD pipeline, have it pause and require manual approval. Never auto-apply replacements.
Common Mistakes to Avoid
Mistake 1: Assuming ~ updates are always safe. Changing certain security group rules can briefly block traffic. Read the specific attribute.
Mistake 2: Ignoring the order of operations. Terraform destroys before creating when replacing. If your new resource depends on the old one (same name), you'll get errors.
Mistake 3: Not checking provider documentation for "forces replacement" attributes. A 5-minute read could prevent 2 hours of downtime.
Conclusion: From Crossing Fingers to Confidence
Terraform plans aren't cryptic—they're precise. We've just been reading them wrong. Start with the filters above, teach your team the three key symbols, and create your own danger checklist. That 200-line output should shrink to 5-10 meaningful lines.
Next time you run terraform plan, don't skim and hope. Filter, translate, and understand. Your infrastructure is telling you exactly what it's about to do. The only question is: are you finally listening?
Quick Summary
- What: Terraform plans are notoriously cryptic and verbose, making it hard to understand what changes will actually happen and whether they're safe
💬 Discussion
Add a Comment