TERRAFORM PLAN BLAST RADIUS CHECK · RUNS IN YOUR BROWSER

Which of these resources is your terraform apply about to destroy?

Paste or load a Terraform structured plan (terraform show -json) and get a deterministic blast-radius report: every destroy and replace called out individually with the attribute that forced it, grouped counts by resource type and by module, and a loud flag when a replace lands on something that holds data.

Nothing is uploaded. The file you load is read in this browser and never leaves your device — which matters here, because a structured plan describes your whole infrastructure.

1. Load your plan

Prefer a CLI, or want this as a gate before you apply?

Same logic, zero dependencies, one file — run it right after you generate the plan, before anything applies it:

terraform plan -out=tfplan && terraform show -json tfplan > plan.json
node cli.mjs check plan.json                            # exit 1 if a replace hits something that holds data
node cli.mjs check plan.json --fail-on=delete-stateful  # also fail on destroying stored data outright
node cli.mjs check plan.json --fail-on=destructive      # fail on any destroy or replace at all
node cli.mjs check plan.json --json

The default gate is replace-stateful rather than "any destroy" on purpose: a gate that fires on every plan in a repository that uses count is one somebody adds continue-on-error to within a week.

Get cli.mjs — Node 18+, nothing to install. It reads only the local file you name: no network call, ever.

Which resource types count as holding data

The heuristic is on the type name, split on underscores and matched against a token list per category. What each category stands to lose:

CategoryWhat a replace costs youExample type tokens

Configuration sub-resources are exempt by suffix — aws_db_parameter_group and aws_s3_bucket_policy carry a stateful token and hold no data of their own. The full reasoning, and the upstream issue that makes this worth a separate tool: why a Terraform replace destroys data, and why the plan does not always tell you which attribute forced it. Already have Sentinel or OPA? see how this checker compares to writing your own policy. Worried about the other thing a plan file exposes? Terraform Plan Secret Exposure Check reads the same file for a different failure — attribute values that look like real secrets which the provider schema never marked sensitive. Want to know what the same plan costs rather than what it destroys? Terraform Plan Cost Estimate prices it per month.

Common questions

Why can't I just read the Plan: N to add, N to change, N to destroy line?

Because a replacement is counted in both the add column and the destroy column, so that line cannot tell you whether the 2 destroys are a pair of scratch resources going away or your production database being recreated empty. The detail that separates them is hundreds of lines further up, in a diff nobody scrolls back through. This tool reads the same plan and puts the replaces and destroys at the top, each with the attribute that forced it.

How does it decide a resource type holds data?

By the resource type name, split on underscores and matched against a token list per category — database, disk or volume, bucket, DNS, load balancer, secret, stateful Kubernetes object, queue or stream, and search cluster. Type names are the one part of a plan that is stable across providers and needs no schema lookup, so this works offline against a provider the tool has never seen. It is deliberately biased toward flagging, because an extra flag costs five seconds of reading and a missed one costs a database, and the report always names the token that matched so you can dismiss a false positive at a glance.

Is my plan uploaded anywhere?

No. The browser page parses a pasted or locally loaded file entirely in your own browser and never sends it anywhere. The CLI reads only a local file — no network call, ever. That matters more than usual here: a structured plan contains your whole infrastructure layout and often real attribute values.

What file does it need?

The structured plan JSON from terraform show -json, not the human-readable terraform plan output and not the line-by-line terraform plan -json stream. Run: terraform plan -out=tfplan && terraform show -json tfplan > plan.json

Why is a replace sometimes listed with no attribute that forced it?

Because the plan did not carry one. replace_paths is populated when a provider marks the change as requiring replacement, but a resource replaced because it is tainted or because you passed -replace=ADDRESS has no forcing attribute at all. In those cases the tool shows the action_reason code instead, which is what the plan does say.

Does a clean report mean the apply is safe?

No. It means nothing in this plan matched the patterns this tool checks. It cannot know that a resource you consider disposable is actually load-bearing, it does not read your state file or your provider's source, and it makes no judgement about the change itself. Read the plan before you apply it — this is one gate, not a guarantee.