State & the plan/apply workflow
init, plan, apply — the same loop.
State is OpenTofu’s memory — a JSON record mapping your configuration to the real resources it manages, so it can compute the difference between what you declared and what exists. The workflow around it is identical to Terraform: init prepares the working directory, plan shows the diff, apply makes it real, destroy tears it down. The plan is the safety mechanism you read before every apply.
$ tofu applyTofu will perform the following actions:# aws_s3_bucket.logs will be created+ resource "aws_s3_bucket" "logs" {+ bucket = "acme-logs-prod"}Plan: 1 to add, 0 to change, 0 to destroy.Do you want to perform these actions? yesaws_s3_bucket.logs: Creation complete after 2s
The state file is compatible with Terraform’s, which is exactly what makes migration painless — but it is also as sensitive as ever, because it can contain resource attributes including secrets in plaintext. Local state (terraform.tfstate on disk) is fine for learning; teams move to a remote backend, and OpenTofu adds the option to encrypt that state, both covered later.