Lesson 3 of 16
Section 1: Foundations, HCL2 Grammar & The Core Lifecycle35 min read & walkthrough

The Lifecycle Loop: Init, Plan, Apply & Destroy

01 / INIT
Provider Lock

Downloads plugin binaries and pins cryptographic checksums into '.terraform.lock.hcl'.

02 / PLAN
Diff Inspection

Read-only preview displaying exact actions (+ create, ~ in-place modify, - destroy).

03 / APPLY
Safe Execution

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.