Your First Configuration
This is the loop every Terraform user runs hundreds of times a day: write a .tf file, terraform init to download providers, terraform plan to preview changes, terraform apply to make them, and terraform destroy to tear them down. Understanding what each step reads and writes — especially that apply creates a state file — is the foundation everything later builds on.
The single most important habit in this whole loop is reading the plan before applying it. The plan is Terraform telling you exactly what it is about to do; skipping it is how people accidentally destroy and recreate a database they meant only to tweak.
Writing the Configuration
A configuration is one or more .tf files in a directory. The minimal one below requires the AWS provider, configures a region, and declares a single S3 bucket. There is no "create" instruction — you declare the bucket that should exist, and Terraform works out that it needs to create it because it does not exist yet.
terraform { required_providers { aws = { source = "hashicorp/aws", version = "~> 6.0" } } } provider "aws" { region = "us-east-1" } resource "aws_s3_bucket" "logs" { bucket = "my-app-logs-7f3a" }
init — Prepare the Working Directory
terraform init reads the configuration, downloads the providers it declares into a local .terraform/ directory, writes the dependency lock file that records exactly which provider versions were chosen, and initializes the backend where state will live. You run it once when you start, and again whenever you add a provider or module. Until you run it, no other command will work, because the providers are not present.
plan — Preview the Changes
terraform plan refreshes the current state from the real world, compares it to your configuration, and prints exactly what it would do — without changing anything. Each line is marked: + to create, ~ to update in place, - to destroy, and -/+ to destroy and recreate. The plan for our bucket shows a single create and changes nothing yet.
# aws_s3_bucket.logs will be created + resource "aws_s3_bucket" "logs" { + bucket = "my-app-logs-7f3a" + id = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy.
apply — Make It Real
terraform apply shows the same plan, asks for confirmation, then executes it — calling the AWS APIs to create the bucket — and records the result in terraform.tfstate. That state file is the new, critical artifact: it maps aws_s3_bucket.logs to the real bucket so the next plan can compute a precise diff. In automation you pair plan -out=tfplan with apply tfplan so apply executes exactly the plan you reviewed.
destroy — Clean Up
terraform destroy plans and executes the removal of everything in state — the clean way to tear down a sandbox so you stop paying for it. It is the inverse of apply, and it operates on what is in state. That detail matters: deleting the .tfstate file by hand does not delete your infrastructure, it just makes Terraform forget the bucket exists, leaving it orphaned in AWS for you to clean up by hand.
- Skipping
planand applying directly, then being surprised when apply destroys and recreates a resource you only meant to tweak. - Running
applywithout reading the plan's destroy lines — the summary count (1 to destroy) is the warning you ignored. - Editing the configuration and forgetting to re-run
initafter adding a provider or module, then getting a "provider not installed" error. - Deleting the
.tfstatefile to "start over" while resources still exist in AWS, orphaning them so you must clean up by hand. - Assuming
applyon a saved plan re-plans against current reality — it executes the frozen plan, which is the point but surprises people.
- Always run and read
terraform planbeforeapply, treating the destroy and replace lines as the thing to verify. - Use
plan -out=tfplanthenapply tfplanin any non-trivial workflow so you apply exactly what you reviewed. - Never hand-delete the state file; use
destroyto remove resources orstate rmto forget them deliberately. - Start every experiment in a throwaway directory or account so
destroyfully cleans up. - Re-run
initafter adding any provider or module, before the next plan.
Knowledge Check
What does terraform plan do?
- Refreshes state, compares it to the config, and prints what it would change — without changing anything
- Downloads the providers, installs the required plugins, and initializes the configured backend before any planning starts
- Applies the changes after a confirmation prompt
- Deletes all resources currently tracked in state
You delete the terraform.tfstate file while the S3 bucket still exists in AWS. What happens?
- The bucket keeps running but Terraform forgets it exists, orphaning it
- The bucket is automatically deleted from AWS
- Terraform recreates the state from AWS on the next plan automatically
- Nothing changes, because state is just a cache that is rebuilt every run
When must you re-run terraform init?
- After adding a new provider or module to the configuration
- Before every single plan, without exception
- Only the very first time you ever use Terraform on the machine
- After every apply, to refresh the state file
Why use plan -out=tfplan followed by apply tfplan in automation?
- So apply executes exactly the plan that was reviewed, not a freshly recomputed one
- It is the only way to run Terraform without internet access, since the saved file bundles every provider plugin offline
- It skips the refresh step to make apply faster
- It encrypts the plan so it cannot be read
You got correct