7.2 Terraform: providers, resources and state
Checked against HashiCorp's Terraform documentation, August 2026
What this is and why it exists
Terraform is the tool most teams reach for to put the previous lesson's argument into practice: you describe infrastructure in files, it works out what to create, change or destroy, and it does that against any provider. This lesson is the working core — the four kinds of block you will write, the state file that everything depends on, and the two habits that stop a learning exercise from becoming a bill.
The vocabulary
- Provider — the plugin that knows how to talk to one platform's API; there is an AWS provider, an AzureRM provider, a Google provider.
- Resource — one piece of infrastructure you want to exist.
- Variable — an input to your configuration, so the same files describe several environments.
- Output — a value the configuration publishes, so other things can use it.
- State — Terraform's record of which real object corresponds to which resource in your files.
- Plan — the preview of what an apply would do.
- Apply — carrying out the plan.
- Destroy — removing everything the configuration manages.
The mental model
Terraform holds three things in its head and compares them: your configuration (what should exist), the state (what it believes exists), and the real platform (what does exist). Every command is a move between those three. The documentation describes a plan doing exactly this — it "reads the current state of any already-existing remote objects to make sure that the Terraform state is up-to-date", then compares "the current configuration to the prior state and noting any differences", then "proposes a set of change actions that should, if applied, make the remote objects match the configuration". Nothing changes yet: "the plan command alone does not actually carry out the proposed changes."
A resource block names a type and a label. The type comes from the provider and decides what is created; the label is yours, and the documentation is clear that Terraform "uses this label to track the resource in your state file. The label does not affect settings on the actual infrastructure resource." That distinction matters more than it looks: renaming the label does not rename anything in the cloud — it tells Terraform that the old thing is gone and a new one is wanted, and the plan will offer to destroy and recreate. Read plans, always.
Now the state file, which is the part of Terraform people underestimate until it hurts. Its purpose, in the documentation's words, is "to store bindings between objects in a remote system and resource instances declared in your configuration" — without it, Terraform cannot tell a resource it created from one that happens to exist. Three facts follow, and all three are operational.
It is sensitive. State records attributes of real resources, and some of those are secrets — a generated password, a connection string. The documentation warns against storing it "in a version control system or other storage solution that does not support Terraform state locking and secure access control, because doing so can result in data loss or exposure of secrets stored in the state file". So: never in Git.
It must be shared, and only one person may write it at a time. Two applies against the same state at once corrupt the record of reality, which is a much worse day than an ordinary failure. The answer is a backend — the block that "defines where Terraform stores its state data files" — pointing at remote storage that supports locking, so a second apply waits instead of racing.
And it can disagree with reality. Somebody changes something by hand and the state is stale until the next refresh; the next plan will offer to change it back. That is the drift conversation from the previous lesson, showing up as a diff you can read.
Then the two habits. Plan before every apply, and read the plan — not the summary line, the actions: what is created, what is changed in place, and what is destroyed and recreated. Almost every expensive Terraform accident was visible in a plan that nobody read. And destroy what you built for practice, deliberately, the same day. terraform destroy "deprovisions all objects managed by a Terraform configuration", and the documentation notes it is a convenience alias for terraform apply -destroy — which is the honest description, since it is an ordinary apply of a plan that removes everything. A lab left running is the most common way a student's free tier becomes a charge.
Portable operations
Checked against HashiCorp's own reference. The shape of a configuration:
terraform {
backend "s3" {
bucket = "my-tfstate"
key = "prod/network.tfstate"
region = "ap-south-1"
}
}
variable "environment" {
type = string
default = "dev"
}
resource "aws_s3_bucket" "uploads" {
bucket = "myapp-uploads-${var.environment}"
}
output "uploads_bucket" {
value = aws_s3_bucket.uploads.bucket
}aws_s3_bucket is the type, from the provider; uploads is the label Terraform records in state. And the loop:
terraform init
terraform plan
terraform apply
terraform destroyinit prepares the working directory and the backend, plan previews without changing anything, apply carries the plan out, and destroy removes everything the configuration manages. Run them in that order every time, and never let the habit of reading the plan lapse because the change looked small.
What you should now be able to explain or do
Name the three things Terraform compares, and say which command does what between them. Write a resource block and say which part is the provider's and which is yours. Explain what a plan does and what it does not do. Give three operational facts about the state file and the practice each one demands. Say why renaming a resource label produces a destroy in the plan. Describe the two habits, and what each one prevents.
Check yourself
What are the three things Terraform compares?
Your configuration, the state file, and the real platform. A plan refreshes state from the platform, compares it to the configuration, and proposes the actions that would close the gap.
Why must the state file never live in Git?
Because it records real attributes, including secrets, and version control offers neither locking nor the access control this needs — the documentation warns it risks both data loss and exposure of secrets.
You rename a resource's label in the configuration. What does the plan say?
That the old resource is destroyed and a new one created. The label is Terraform's own record-keeping name and does not touch the real object, so a rename reads as one thing disappearing and another appearing.
What does terraform plan change?
Nothing. It refreshes state and proposes actions; the documentation says plainly that the command alone does not carry out the proposed changes.
What is the most common way a practice project becomes a bill?
Not destroying it. Run terraform destroy the same day you finish — an alias for an apply that removes everything the configuration manages — rather than leaving a lab running and forgetting the meter.
Go deeper
We haven't checked most of these for screen reader use yet.
Back to Terraform: providers, resources and state: work through the checklist