Skip to main content

AI & assistant-friendly summary

This section provides structured content for AI assistants and search engines. You can cite or summarize it when referencing this page.

Summary

Every Terraform command you actually need on AWS — modernized for Terraform 1.10+, with deprecated commands flagged and AWS-specific gotchas for state, workspaces, providers, and the new import/removed/ephemeral primitives.

Key Facts

  • Every Terraform command you actually need on AWS — modernized for Terraform 1
  • 10+, with deprecated commands flagged and AWS-specific gotchas for state, workspaces, providers, and the new import/removed/ephemeral primitives
  • Every Terraform command you actually need on AWS — modernized for Terraform 1
  • 10+, with deprecated commands flagged and AWS-specific gotchas for state, workspaces, providers, and the new import/removed/ephemeral primitives

Entity Definitions

Terraform
Terraform is a development tool discussed in this article.

The Terraform Command Cheat Sheet for AWS Engineers (2026 Edition)

DevOps & CI/CD Palaniappan P 11 min read

Quick summary: Every Terraform command you actually need on AWS — modernized for Terraform 1.10+, with deprecated commands flagged and AWS-specific gotchas for state, workspaces, providers, and the new import/removed/ephemeral primitives.

Key Takeaways

  • Every Terraform command you actually need on AWS — modernized for Terraform 1
  • 10+, with deprecated commands flagged and AWS-specific gotchas for state, workspaces, providers, and the new import/removed/ephemeral primitives
  • Every Terraform command you actually need on AWS — modernized for Terraform 1
  • 10+, with deprecated commands flagged and AWS-specific gotchas for state, workspaces, providers, and the new import/removed/ephemeral primitives
The Terraform Command Cheat Sheet for AWS Engineers (2026 Edition)
Table of Contents

Terraform isn’t really about writing code. It’s about managing state and lifecycle.

That framing matters because the commands you’ll actually reach for in a production AWS environment are not the ones you used in your first tutorial. Five years ago a Terraform cheat sheet was a list of thirty CLI verbs. In 2026, half of that list has either been deprecated, replaced by a declarative HCL primitive, or become AWS-specific in ways that aren’t obvious from --help.

This is the version of the cheat sheet I’d want on a wiki for an AWS team running Terraform 1.10+. Each command shows the syntax, when it’s the right tool, and the AWS-specific gotcha that bites real teams. Where a command is deprecated or has a better modern equivalent, I’ll say so and show what to use instead.

If you’re still deciding between Terraform and a higher-level abstraction, start with our Terraform vs AWS CDK decision guide and come back here once you’ve picked a side.

What’s New Since You Last Looked

Six things changed between Terraform 1.5 and 1.10 that the older cheat sheets you’ll find on the internet don’t cover:

  • import {} blocks (1.5+) — declarative imports, plannable, reviewable in PRs
  • terraform plan -generate-config-out (1.5+) — auto-scaffold resource code from imports
  • check {} blocks (1.5+) — runtime assertions inside your config
  • terraform test (1.6+) — first-class HCL test framework
  • removed {} blocks (1.7+) — declaratively drop from state without destroying real infra
  • Ephemeral resources & write-only attributes (1.10+) — secrets that never persist to state
  • S3 native state locking (1.10+) — DynamoDB lock table is no longer required
  • terraform apply -replace (since 0.15.2) — the modern replacement for the deprecated terraform taint

We’ll hit each of these in context as we go through the lifecycle.

Core Lifecycle Commands

These are the four or five commands you run dozens of times a day.

terraform init

Initializes the working directory: downloads providers, configures the backend, builds the module dependency graph, writes .terraform.lock.hcl.

terraform init
terraform init -upgrade                    # upgrade provider versions within constraints
terraform init -reconfigure                # ignore existing backend config
terraform init -migrate-state              # move state between backends

AWS note: init is where the AWS provider’s credential chain is resolved — environment variables → shared config (~/.aws/credentials, AWS_PROFILE) → IRSA on EKS → EC2 instance metadata (IMDS). If init fails with cryptic credential errors, the issue is almost always one of those layers, not Terraform itself. Confirm with aws sts get-caller-identity before debugging further.

terraform validate

Schema and syntax check. Doesn’t hit AWS. Run it as a pre-commit hook and in CI before you spend money on a plan.

terraform validate

terraform fmt

Canonicalizes HCL formatting.

terraform fmt -recursive       # whole repo
terraform fmt -check -recursive  # CI mode — non-zero exit if anything would change

terraform plan

The single most important command in your workflow. It reads your code, refreshes state from AWS, and tells you exactly what will change.

terraform plan
terraform plan -out=tfplan          # save the plan for promotion
terraform plan -refresh-only        # detect drift without proposing changes
terraform plan -target=module.vpc   # narrow scope (use sparingly)

AWS note: Always save the plan and apply the saved file in production. The “promote-the-plan” pattern is the only way to guarantee that the change you reviewed is the change you applied. We cover the full pattern in Safe Terraform Apply Workflows on AWS.

terraform apply

Applies a saved plan, or creates a new one and applies it after confirmation.

terraform apply tfplan                                # apply a saved plan
terraform apply                                       # plan + apply (interactive)
terraform apply -auto-approve                         # skip confirmation (CI only)
terraform apply -replace="aws_instance.web"           # force-recreate one resource
terraform apply -destroy                              # safer than `terraform destroy`

The -replace flag is the modern replacement for terraform taint. Taint mutated state immediately and silently; -replace shows the recreate inside the plan output, where you can review it. If you’re still typing terraform taint, retrain that muscle memory.

terraform destroy

Tears everything down. Useful for ephemeral environments and PR previews; risky enough in production that you should prefer terraform apply -destroy, which routes the operation through the same plan-and-approve flow as any other apply.

terraform destroy
terraform destroy -target=aws_instance.tmp

terraform refresh (mostly retired)

The standalone refresh command still exists but is effectively superseded by terraform plan -refresh-only, which lets you see what’s drifted before you write to state.

terraform plan -refresh-only      # preferred — visible diff
terraform apply -refresh-only     # apply the drift correction with approval

Inspecting Your Configuration

These are the read-only commands. Use them liberally; none of them touch AWS resources.

terraform show

Renders state, or a saved plan, into human-readable text. The -json form is what powers your policy-as-code tooling.

terraform show                            # current state
terraform show tfplan                     # saved plan, human-readable
terraform show -json tfplan | jq .        # machine-readable — feed to OPA, Sentinel, Checkov

terraform output

Reads outputs from state. The JSON form is what you wire into CodePipeline, GitHub Actions, or downstream Terraform configs.

terraform output
terraform output alb_dns_name
terraform output -json | jq .alb_dns_name.value

terraform graph

Renders the dependency graph as DOT. Useful in architecture reviews when someone asks “wait, what depends on the NAT gateway?”

terraform graph | dot -Tsvg > graph.svg

terraform providers

Audits which providers and versions are actually in use. Critical when you’re tracking down “why did aws_eks_cluster start behaving differently after init -upgrade?”

terraform providers
terraform providers schema -json | jq .

terraform version

The most boring command in this cheat sheet, and the one you should print at the top of every CI run. Pinning the Terraform binary version is as important as pinning the AWS provider — see our AWS provider upgrade strategy for the full pattern.

terraform version

State Management

State is the source of truth for what Terraform thinks exists in AWS. The state commands let you reshape that truth without rebuilding real infrastructure.

Reading state (always safe)

terraform state list                              # every resource address
terraform state list 'module.vpc.*'               # filter
terraform state show aws_db_instance.primary      # one resource's attributes

Moving and removing state

terraform state mv aws_instance.old aws_instance.new   # rename
terraform state rm aws_s3_bucket.deleted_in_console    # forget without destroying

Modern equivalent: Prefer the declarative HCL blocks where possible. Both leave a paper trail in git that ad-hoc CLI commands don’t.

moved {
  from = aws_instance.old
  to   = aws_instance.new
}

removed {
  from = aws_s3_bucket.legacy
  lifecycle {
    destroy = false   # forget from state, leave the bucket alone in AWS
  }
}

Importing existing AWS resources

The CLI form still works:

terraform import aws_s3_bucket.logs my-bucket-name

But for anything bigger than a one-off, the modern import {} block is the right tool. It’s plannable, reviewable, and pairs with -generate-config-out to write the resource block for you.

import {
  to = aws_s3_bucket.logs
  id = "my-bucket-name"
}
terraform plan -generate-config-out=imported.tf

For the operational mechanics — AWS resource ID quirks, importing security groups, RDS, IAM — see our deep dive on Terraform State Management on AWS.

terraform force-unlock

The “stuck pipeline” command. CodeBuild gets killed mid-apply, the lock entry stays in S3 (or DynamoDB on legacy backends), and every subsequent apply blocks. Use only when you’re certain no one else is running an apply.

terraform force-unlock <LOCK_ID>

Workspaces

Workspaces split state inside a single backend.

terraform workspace list
terraform workspace new staging
terraform workspace select staging
terraform workspace delete old-feature-branch

Honest production take: workspaces are great for ephemeral dev branches and PR preview environments. They are not the right tool for separating production from staging on AWS. For that, use separate AWS accounts, separate state files, and separate IAM roles — the blast radius of a misconfigured workspace switch is your entire prod environment. We cover the multi-account pattern in our AWS managed services work.

Provider Lockfile and Multi-Platform CI

.terraform.lock.hcl pins exact provider versions and SHA256 hashes. Commit it.

terraform init -upgrade   # writes a new lock file with current versions

If your team builds in CodeBuild (Linux) and develops on Apple Silicon Macs, you need to pre-hash the provider for every platform you’ll touch. Otherwise the first developer to run init on a different OS rewrites the lockfile and breaks CI for everyone else.

terraform providers lock \
  -platform=linux_amd64 \
  -platform=linux_arm64 \
  -platform=darwin_amd64 \
  -platform=darwin_arm64

Run this any time you bump the AWS provider. Detailed walkthrough: Upgrading the AWS Terraform Provider Safely.

Modern Primitives the Old Cheat Sheets Miss

This is where Terraform has actually changed. If you’re running 1.10+, these belong in your toolkit.

import {} blocks (1.5+)

Already shown above. The headline benefit: imports become reviewable like any other code change. No more “wait, who imported the prod RDS into the staging state?”

removed {} blocks (1.7+)

Declaratively forget a resource without destroying the real AWS object. The classic use case is splitting one Terraform configuration into two — you remove from the source, import into the target, and the underlying AWS resource never restarts.

check {} blocks (1.5+)

Runtime assertions that run during plan and apply. Good for catching misconfigurations before they ship.

check "alb_uses_https" {
  assert {
    condition     = alltrue([for l in aws_lb_listener.public : l.protocol == "HTTPS"])
    error_message = "All public ALB listeners must terminate TLS."
  }
}

terraform test (1.6+)

A real test framework. Write *.tftest.hcl files alongside your modules and run them in CI before merging.

terraform test
terraform test -filter=tests/network.tftest.hcl

If you maintain a shared module library on AWS — VPC modules, EKS modules, ALB modules — adopting terraform test is the single highest-leverage thing you can do this quarter.

Ephemeral resources & write-only attributes (1.10+)

Some values shouldn’t ever land in terraform.tfstate — and your state file lives in S3, where it’s read by everyone with backend access. Ephemeral resources and write-only attributes let you pass secrets through Terraform without persisting them.

ephemeral "aws_secretsmanager_secret_version" "db_password" {
  secret_id = aws_secretsmanager_secret.db.id
}

resource "aws_db_instance" "primary" {
  password_wo         = ephemeral.aws_secretsmanager_secret_version.db_password.secret_string
  password_wo_version = 1
  # ...
}

The password flows from Secrets Manager into RDS at apply time and never appears in state, plan output, or your S3 backend.

S3 native state locking (1.10+)

The DynamoDB lock table is no longer required. New AWS deployments should use the native S3 lock.

terraform {
  backend "s3" {
    bucket       = "company-tf-state"
    key          = "platform/prod/terraform.tfstate"
    region       = "us-east-1"
    encrypt      = true
    use_lockfile = true   # native S3 locking, no DynamoDB needed
  }
}

Existing teams don’t need to migrate immediately — the DynamoDB pattern still works — but new state files should skip the DynamoDB hop entirely.

HCP Terraform, OpenTofu, and the License Question

terraform login
terraform logout

login stores an HCP Terraform (formerly Terraform Cloud) token. You only need it if your team runs HCP-managed workspaces.

A note on OpenTofu: in August 2023 HashiCorp moved Terraform to the Business Source License. The community forked the last MPL-licensed version into OpenTofu, which has shipped competitive features (state encryption, dynamic provider configuration) since. Commands are interchangeable — tofu init, tofu plan, tofu apply accept the same flags as their terraform equivalents, and HCL, state files, providers, and modules all work on both. For most AWS-focused teams, the choice comes down to vendor relationship and feature roadmap, not technical compatibility.

Console and Debugging

terraform console

Underrated. An interactive REPL with full access to your state, variables, and locals — perfect for testing an interpolation before committing the change.

terraform console
> aws_instance.web.private_ip
> [for s in aws_subnet.private : s.cidr_block]

TF_LOG for AWS provider debugging

When the AWS provider does something weird, the answer is usually in the trace.

TF_LOG=DEBUG terraform plan 2> tf-debug.log
TF_LOG=TRACE terraform apply 2> tf-trace.log

TRACE is verbose enough that you’ll want to redirect to a file. The AWS API requests and responses, including the exact STS, IAM, and service calls Terraform is making on your behalf, are in there.

Cheat Sheet — Quick Reference

PhaseCommandNotes
Initterraform initBackend + providers + lockfile
Initterraform init -upgradeRefresh provider versions
Initterraform init -migrate-stateMove backends
Lifecycleterraform validateSchema check, no AWS calls
Lifecycleterraform fmt -check -recursiveCI formatting gate
Lifecycleterraform plan -out=tfplanSave plan for promotion
Lifecycleterraform apply tfplanApply saved plan
Lifecycleterraform apply -replace=ADDRModern replacement for taint
Lifecycleterraform apply -destroySafer than terraform destroy
Lifecycleterraform plan -refresh-onlyDrift detection
Lifecycleterraform taintDeprecated — use apply -replace
Lifecycleterraform untaintDeprecated — N/A in modern flow
Lifecycleterraform refreshMostly retired — use plan -refresh-only
Inspectterraform show -jsonFeeds policy-as-code
Inspectterraform output -jsonPipe to CI/CD
Inspectterraform graphDependency visualization
Inspectterraform providersAudit provider versions
Inspectterraform versionPin in CI logs
Stateterraform state listRead-only
Stateterraform state show ADDRRead-only
Stateterraform state mvPrefer moved {} block
Stateterraform state rmPrefer removed {} block
Stateterraform import ADDR IDPrefer import {} block
Stateterraform force-unlock IDStuck-pipeline rescue
Workspaceterraform workspace new/select/list/deleteDev/PR previews only
Providerterraform providers lock -platform=...Cross-platform CI
Cloudterraform login / logoutHCP Terraform
Debugterraform consoleInteractive REPL
DebugTF_LOG=DEBUG terraform planProvider tracing
Modern HCLimport {} block (1.5+)Declarative imports
Modern HCLmoved {} blockReviewable refactors
Modern HCLremoved {} block (1.7+)Drop from state safely
Modern HCLcheck {} block (1.5+)Runtime assertions
Modern CLIterraform test (1.6+)HCL test framework
Modern HCLephemeral resources (1.10+)Secrets that never hit state
Modern Backenduse_lockfile = true (1.10+)S3 native locking, no DynamoDB

Where to Go From Here

The commands are the easy part. The hard part is the workflow around them — who can apply, where state lives, how rollback works when an apply goes sideways. The companion posts on this site go deep on those:

If you’re standing up Terraform on AWS for the first time — or rescuing a setup that’s drifted into legacy patterns — FactualMinds helps AWS teams operationalize Terraform end-to-end: backend architecture, CI/CD apply pipelines, state segmentation across accounts, and provider upgrade discipline. See our DevOps pipeline setup service or talk to an architect about your environment.

PP
Palaniappan P

AWS Cloud Architect & AI Expert

AWS-certified cloud architect and AI expert with deep expertise in cloud migrations, cost optimization, and generative AI on AWS.

AWS ArchitectureCloud MigrationGenAI on AWSCost OptimizationDevOps

Ready to discuss your AWS strategy?

Our certified architects can help you implement these solutions.

Recommended Reading

Explore All Articles »