The Lifecycle Loop: Init, Plan, Apply & Destroy
Downloads plugin binaries and pins cryptographic checksums into '.terraform.lock.hcl'.
Read-only preview displaying exact actions (+ create, ~ in-place modify, - destroy).
Requires human confirmation before making real mutating API calls against cloud endpoints.
The Big Idea
The day-to-day workflow of Infrastructure as Code revolves around four essential commands: init, plan, apply, and destroy. Knowing exactly what happens under the hood during each step is what separates junior script runners from senior infrastructure architects.
When you run terraform init, Terraform parses your configuration, discovers required provider plugins, fetches the compiled binaries from the registry, and verifies their SHA-256 cryptographic hashes against the lock file .terraform.lock.hcl.
When you run terraform plan, Terraform performs a 100% read-only audit. It contacts cloud APIs to refresh its mental model of existing infrastructure, reads your local code, and presents an exact diff showing additions (+), in-place updates (~), and destructive replacements (-/+). Nothing in your cloud account is mutated until you review this plan and authorize terraform apply.
Jargon Buster: Plain-English Translations
- Lock File (.terraform.lock.hcl): A version control file that locks provider versions and hashes to ensure deterministic team execution across workstations.
- Plan Speculative Diff: The calculated delta between the current cloud state, the local state file, and the desired code.
- In-Place Update (~): An attribute change that cloud APIs support without tearing down and recreating the underlying resource.
- Destructive Replacement (-/+): An attribute modification (such as changing an EC2 AMI or VPC CIDR) that forces cloud APIs to delete and recreate the resource.
Understanding Plan Output Diff Symbols
# Terraform will perform the following actions:
# aws_vpc.core will be updated in-place (Non-destructive)
~ resource "aws_vpc" "core" {
id = "vpc-0a81b2c3d4e5f6g7"
~ enable_dns_hostnames = false -> true
tags = {
"Environment" = "production"
"Name" = "core-enterprise-vpc"
}
# (3 unchanged attributes hidden)
}
# aws_security_group_rule.allow_tls will be created
+ resource "aws_security_group_rule" "allow_tls" {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ from_port = 443
+ id = (known after apply)
+ protocol = "tcp"
+ security_group_id = "sg-0123456789abcdef0"
+ to_port = 443
+ type = "ingress"
}
Plan: 1 to add, 1 to change, 0 to destroy.
Beginner Traps & Gotchas
1. Carelessly running with -auto-approve flag in production
The Gotcha: Bypassing the interactive plan prompt and accidentally approving a hidden '-/+' replacement that destroys a production database.
The Fix: Never use '-auto-approve' outside automated CI/CD staging pipelines. Always generate an explicit speculative plan file with 'terraform plan -out=tfplan' and apply that exact file.
2. Ignoring the .terraform.lock.hcl in git repositories
The Gotcha: Adding '.terraform.lock.hcl' to .gitignore, causing team members to build with mismatched provider versions.
The Fix: Always commit '.terraform.lock.hcl' into version control. It guarantees identical provider behavior across all machines.