Skip to content
CloudOps
Newsletter
All guides
AI for Terraform By James Joyner IV · · 15 min read

How AI Helps DevOps Engineers Write Better Terraform Code

AI helps DevOps engineers write better Terraform code by reviewing plans for security and cost risk, generating modules you verify, and refactoring safely.

  • #terraform
  • #ai
  • #iac
  • #code-review
  • #devops

AI helps you write better Terraform by reviewing your configs and plans for security, cost, and correctness problems before they reach production; by generating boilerplate, modules, and validation rules that you read and verify; by explaining cryptic plan output and provider errors in plain language; and by refactoring large configurations with moved and import blocks instead of risky hand edits. The non-negotiable boundary is that a human always reads the terraform plan and runs terraform apply — the model never gets cloud credentials, never touches state, and never auto-applies its own output. Used that way, AI is the fastest senior reviewer you have ever paired with. Used carelessly, it is a confident junior who will happily open an S3 bucket to the world and tell you it looks great.

I have spent the last couple of years putting AI in the loop on real Terraform across several teams, and the pattern that works is consistent: AI proposes, the tooling validates, and a human decides. This post walks through the concrete ways that loop makes your HCL better — with the exact prompts I use, what good output looks like, and the real config that comes out the other side. If you want the running tooling instead of the theory, the Infrastructure Code Review dashboard implements most of this as a service.

Can AI review my Terraform for security issues?

Yes, and this is the single highest-value use. Static scanners like tfsec and checkov catch known-bad patterns by rule, but they miss intent — they do not know that this bucket is supposed to be private or that this security group should never expose 0.0.0.0/0. AI fills that gap because you can hand it both the config and the context.

Here is a config I genuinely received in a pull request:

resource "aws_s3_bucket" "reports" {
  bucket = "acme-financial-reports"
}

resource "aws_s3_bucket_public_access_block" "reports" {
  bucket                  = aws_s3_bucket.reports.id
  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}

resource "aws_security_group" "db" {
  name = "postgres-sg"
  ingress {
    from_port   = 5432
    to_port     = 5432
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

The prompt I use is deliberately adversarial:

You are a senior security reviewer. Here is Terraform for an internal financial-reporting system. The S3 bucket must be private. The Postgres instance is only accessed from our app subnet (10.0.16.0/20). List every security finding with severity, the exact resource, and the corrected HCL. Do not soften findings.

Good output names the bucket public-access-block as critical (it disables all four protections on a financial bucket), flags the missing default encryption and the absence of a bucket policy, and rewrites the security group to scope ingress to 10.0.16.0/20. Bad output says “looks mostly fine, consider tightening.” The framing — naming the system, stating the intent, forbidding hedging — is what separates the two. AI is good at security review precisely when you give it the security context the scanner can never have. For a deeper rule-based pass, pair it with tfsec and checkov and let AI explain and fix what they flag.

Can AI explain a scary Terraform plan?

A terraform plan that shows 12 to add, 4 to change, 3 to destroy is the moment most outages are born — someone skims it, sees green, and applies. AI turns that wall of diff into a risk briefing.

The plan output you want to feed it is the machine-readable JSON, not the colored terminal text:

terraform plan -out=tfplan.binary
terraform show -json tfplan.binary > plan.json

Then:

Here is a terraform plan in JSON. Group changes into: (1) destructive — anything destroyed or replaced, (2) potentially destructive — in-place changes to data resources, (3) safe additions. For every replace, tell me which attribute forces it and whether it implies data loss or downtime. Output a table sorted by blast radius.

What good output looks like: it catches that an aws_db_instance is being replaced because someone changed engine_version in a way that forces recreation, flags the implied data loss, and notices a tags change buried under it that is harmless. The value is not the summary — it is the prioritization. The model surfaces the one line in 400 that will page you at 2am. I never let it run the plan or hold credentials; I generate the JSON myself and paste it. The code review dashboard does exactly this triage on the JSON you upload.

How do I get AI to generate a reusable module?

AI is excellent at module scaffolding because module quality is mostly about interface discipline — clear variables, sane defaults, validated inputs, useful outputs — and that is pattern work. The trick is to design the interface in the prompt rather than asking for “a module.”

Write a reusable Terraform module for an AWS SQS queue with a dead-letter queue. Variables: name (required), max_receive_count (default 5), visibility_timeout_seconds (default 30, must be 0–43200), tags (map). Output the main queue ARN and URL and the DLQ ARN. Add variable validation for every constraint. Pin the AWS provider to ~> 5.0. No hardcoded regions or account IDs.

Good output gives you a clean interface with validation baked in:

variable "visibility_timeout_seconds" {
  type    = number
  default = 30
  validation {
    condition     = var.visibility_timeout_seconds >= 0 && var.visibility_timeout_seconds <= 43200
    error_message = "visibility_timeout_seconds must be between 0 and 43200."
  }
}

resource "aws_sqs_queue" "dlq" {
  name = "${var.name}-dlq"
  tags = var.tags
}

resource "aws_sqs_queue" "main" {
  name                       = var.name
  visibility_timeout_seconds = var.visibility_timeout_seconds
  redrive_policy = jsonencode({
    deadLetterTargetArn = aws_sqs_queue.dlq.arn
    maxReceiveCount     = var.max_receive_count
  })
  tags = var.tags
}

output "queue_arn" {
  value = aws_sqs_queue.main.arn
}

You still read every line — I have seen AI invent attributes that do not exist on a resource, or pick a redrive_policy shape that drifts on the next plan. But starting from a validated skeleton beats starting from a blank file. If you want battle-tested, copy-paste prompts for module design and the rest of these workflows, the Terraform prompt pack collects them with fill-in placeholders and safety notes.

How does AI help write variable validation that actually holds?

Most Terraform breaks not at apply but three weeks later when someone passes a malformed input. Validation blocks are tedious to write by hand, which is exactly why people skip them — and exactly where AI earns its keep.

For this instance_type variable, write validation that only allows the t3 and m6i families, and for this environment variable, only allow dev, staging, prod. Give clear error messages naming the allowed values.

variable "instance_type" {
  type = string
  validation {
    condition     = can(regex("^(t3|m6i)\\.", var.instance_type))
    error_message = "instance_type must be in the t3 or m6i family (e.g. t3.medium)."
  }
}

variable "environment" {
  type = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "environment must be one of: dev, staging, prod."
  }
}

Good output uses contains() for enums and can(regex(...)) for patterns, and writes error messages a teammate can act on. The win is throughput — AI writes ten of these in the time it takes you to look up the regex for one. You review the conditions, because a too-loose regex is worse than none.

Can AI catch a missing prevent_destroy or lifecycle gap?

This is the kind of review humans are bad at because it is about what is not in the file. Stateful resources — RDS instances, S3 buckets with data, EBS volumes — should usually carry lifecycle { prevent_destroy = true }, and nobody remembers every time.

Scan this Terraform. List every stateful resource (databases, persistent storage, anything holding data) that lacks prevent_destroy. For each, show the lifecycle block to add. Ignore stateless resources.

resource "aws_db_instance" "main" {
  # ...
  lifecycle {
    prevent_destroy = true
  }
}

Good output distinguishes stateful from stateless instead of slapping prevent_destroy on every resource (which makes future refactors miserable). This is a great example of AI reviewing for correctness of omission — the bug that has no line number.

How does AI help refactor a giant config without breaking state?

Refactoring Terraform is dangerous because renaming a resource or splitting a file makes Terraform think you destroyed one thing and created another. The safe path is moved blocks (and import for adopting existing infra), and AI is good at generating these mechanically from a before/after diff.

Say you are renaming aws_instance.web to aws_instance.app and moving it into a module. By hand this is error-prone. With AI:

I am renaming aws_instance.web to module.compute.aws_instance.app. Generate the moved block so Terraform updates state in place instead of destroy/recreate. Then tell me exactly what terraform plan should show if the move is correct.

moved {
  from = aws_instance.web
  to   = module.compute.aws_instance.app
}

The crucial second half of that prompt — “tell me what the plan should show” — gives you a verification expectation. Good output says: the plan must show 0 to add, 0 to destroy, only the address moving. If your actual plan shows a destroy, the move is wrong and you stop. That expectation is your safety net. AI generates the boilerplate; the plan is the proof. For adopting existing cloud resources, the same workflow produces import blocks, and you verify them the same way — by reading the plan, never by trusting the model.

Can AI make my Terraform cost-aware?

AI will not replace infracost, but it reasons about cost shape in a way scanners do not. Feed it a config and ask the questions a finance-minded reviewer would.

Review this Terraform for cost risk. Flag: oversized instances for a dev environment, missing autoscaling on always-on resources, NAT gateways that could be a single shared one, gp2 volumes that should be gp3, and any resource with no lifecycle to tear down in non-prod.

Good output spots three db.r6g.2xlarge instances tagged environment = "dev" and asks whether dev needs that, notes one NAT gateway per AZ where a single one would do for a test account, and recommends gp3 over gp2. It is directional, not exact — you confirm real numbers with infracost in CI — but it catches the expensive design decisions before they are committed. The best results come from running both: AI for “is this the right shape,” infracost for “what does it cost.”

How does AI help with drift triage?

When drift detection fires, the question is always did a human make an intentional out-of-band change, or did something break? AI helps you triage the diff without blindly running terraform apply to “fix” it — which can overwrite a legitimate manual hotfix.

Here is a drift diff between state and reality. For each drifted attribute, classify it as: likely intentional manual change, likely external automation, or likely corruption. Recommend whether to update the config to match reality, refresh state, or investigate — but do NOT recommend a blind reapply.

The value here is the explicit refusal to reflexively reapply. Good output reasons about each attribute — a changed tag is probably a human, a flipped desired_count is probably an autoscaler — and routes you to the right fix. I keep the model on the read side of this entirely; it sees the diff text, never the live account.

Can AI write Terraform tests and policy-as-code?

Yes, and this is where AI pays compounding dividends, because tests and policies are the things teams perpetually mean to write and never do.

For native tests (terraform test), AI scaffolds the .tftest.hcl files:

Write a terraform test that asserts this S3 module sets force_destroy = false and blocks all public access. Use mock providers so it runs offline with no AWS credentials.

For policy-as-code, it drafts OPA/Rego or Sentinel rules from a plain-English policy:

Write an OPA policy that denies any aws_security_group ingress rule allowing 0.0.0.0/0 on ports other than 80 and 443.

Good output for tests uses mocks so the suite runs in CI without credentials; good policy output denies by default and is specific about the exception. You review the assertions hard, because a test that asserts nothing meaningful is worse than no test — it manufactures false confidence. The point of AI here is to get past the blank-page tax, not to skip the review.

The copy-paste Terraform code review prompt

This is the prompt I keep pinned. Paste your .tf (and optionally the plan JSON) below it:

You are a senior Terraform reviewer with a security and reliability bias.
Review the configuration below. Assume it targets production unless I say
otherwise. Do not hedge or soften findings.

Report findings in these buckets, each with severity (critical/high/med/low),
the exact resource address, and corrected HCL:

1. SECURITY — public exposure, open security groups, missing encryption,
   over-broad IAM, secrets in plaintext, disabled public-access blocks.
2. DATA SAFETY — stateful resources missing prevent_destroy; changes that
   force replace and imply data loss; force_destroy = true on real data.
3. CORRECTNESS — invalid/nonexistent attributes, type mismatches, count/
   for_each misuse, wrong references, provider version gaps.
4. MAINTAINABILITY — missing variable validation, hardcoded regions/account
   IDs/AMIs, no outputs, copy-paste that should be a module.
5. COST — oversized resources, missing lifecycle in non-prod, per-AZ NAT
   gateways, gp2 where gp3 fits.

End with a SHIP / DO NOT SHIP verdict and the single most dangerous line.
Do not invent attributes; if unsure whether one exists, say so.

The “do not invent attributes” line matters more than it looks — it is the most common failure mode, and naming it cuts hallucinated HCL noticeably. You can run this by hand in Claude or Cursor, or use the Infrastructure Code Review dashboard, which wraps this kind of review with a static pre-scan and a risk floor so the AI cannot quietly downgrade a critical finding.

The hard boundary: what AI must never do

Everything above works because of a wall I never cross, and neither should you:

  • Never auto-apply AI output. The model proposes HCL; a human reads the resulting terraform plan and runs terraform apply. No agent, no pipeline step, applies what an LLM wrote without a human reading the plan first.
  • Never give the model cloud credentials or state-write access. It reviews text — config, plan JSON, drift diffs — that you extract and paste. It does not run terraform, does not hold AWS keys, does not touch the backend. State is the crown jewels; an LLM has no business writing to it.
  • The plan is the source of truth, not the chat. When AI claims a moved block is safe, you verify by reading the plan, not by trusting the explanation. If the plan disagrees with the model, the plan wins, every time.
  • Treat every line as junior-engineer output. Confident and frequently wrong about attribute names and resource semantics. Review accordingly.

Hold that line and AI is a force multiplier. Drop it and you have automated the production of confident, plausible, occasionally catastrophic infrastructure.

FAQ

Will AI write production Terraform for me end to end? No, and you should not want it to. It writes excellent first drafts — modules, validation, tests, refactor blocks — but production-grade means a human read the plan, understood the blast radius, and chose to apply. AI gets you to the review faster; it does not replace the review.

Is it safe to paste my .tf into ChatGPT or Claude? Config files are usually fine — they describe desired state, not secrets, if you manage secrets properly (via a secrets manager, not hardcoded). Never paste terraform.tfstate, .tfvars with real credentials, or actual API keys. If you have any in your HCL, that is a finding to fix before you even think about pasting. For sensitive environments, use a tool with a data-handling agreement rather than a consumer chat.

Can AI fix my Terraform errors? Often, yes — cryptic provider errors, type mismatches, for_each over the wrong collection, version-constraint conflicts. Paste the full error plus the relevant config and ask for the root cause, not just the patch. The risk is a fix that silences the error without addressing the cause, so always confirm with a clean terraform validate and terraform plan.

How is this different from tfsec or checkov? Those are rule engines — fast, deterministic, and blind to intent. AI reasons about context: that this bucket should be private, that this replace means data loss. Best practice is both — scanners as the deterministic floor, AI for the judgment calls — which is exactly how the code review dashboard is built.

Do I need a paid plan for any of this? The prompts work in any capable model. The hosted tooling and prompt packs are optional accelerators; see pricing for what is included, and the prompts library for free starting points.

Conclusion

AI makes you a better Terraform engineer not by writing your infrastructure but by reviewing it harder, faster, and more consistently than you can alone — catching the public bucket, the forced replace, the missing prevent_destroy, the cost you would not have noticed until the bill arrived. The whole discipline reduces to one habit: let AI propose, let your tooling validate, and let a human read the plan before apply. Keep that loop intact and your HCL gets measurably better. Break it and you have just automated your next incident. Start with the review prompt above, keep the boundary, and ship better infrastructure.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.