IaC Concepts & TF Overview
Understand core Infrastructure as Code (IaC) concepts and the role of Terraform in automating cloud infrastructure. Declarative vs imperative, idempotency, IaC tool comparison, and why Terraform's provider model wins at multi-cloud scale.
Infrastructure as Code (IaC) Concepts
What is IaC?
Infrastructure as Code means managing and provisioning infrastructure through machine-readable configuration files instead of manual GUI clicks or ad-hoc scripts.
Instead of logging into the AWS Console and clicking "Launch Instance", you write:
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
}
Run terraform apply and the instance exists. Run terraform destroy and it's gone. The configuration file is the source of truth — not the cloud console, not a wiki page, not someone's memory.
Declarative vs Imperative IaC
The most important conceptual split in IaC:
| Declarative | Imperative | |
|---|---|---|
| You specify | What the end state should be | Step-by-step instructions to get there |
| The tool figures out | How to create/update/delete to reach that state | Nothing — you write every step |
| Example | Terraform, CloudFormation, Pulumi | Ansible playbooks, Bash scripts, AWS CLI |
| Idempotency | Built-in — run it 10 times, same result | You must implement it yourself |
| Drift handling | Compares desired state to real state automatically | Manual |
Terraform is declarative. You write the desired end state in HCL. Terraform determines what needs to be created, updated, or deleted to reach it. Run terraform apply on an already-applied config and Terraform does nothing — the state already matches.
Ansible is imperative by default. A playbook that runs apt install nginx will try to install nginx every time it runs. You add when: conditions to make it idempotent — the burden is on you.
Idempotency
An operation is idempotent if running it multiple times produces the same result as running it once.
Terraform achieves idempotency through its state file: it records the current real-world state after each apply. On the next apply, it compares your config to the state and only changes what's different. If nothing changed, terraform apply is a no-op.
This matters for CI/CD: you can run terraform apply on every merge to main and it won't duplicate resources.
IaC Tool Comparison
| Tool | Model | Language | Scope | Multi-cloud |
|---|---|---|---|---|
| Terraform | Declarative | HCL | Infrastructure provisioning | ✅ Best-in-class |
| OpenTofu | Declarative | HCL | Terraform fork (open source) | ✅ |
| Pulumi | Declarative | Python / TS / Go / C# | Infrastructure provisioning | ✅ |
| AWS CloudFormation | Declarative | JSON / YAML | AWS only | ❌ AWS-only |
| Azure Bicep | Declarative | Bicep DSL | Azure only | ❌ Azure-only |
| Ansible | Imperative (mostly) | YAML | Config mgmt + provisioning | ✅ |
| Chef / Puppet | Declarative | Ruby DSL | Config management | ✅ |
When Terraform wins: provisioning cloud infrastructure (VPCs, VMs, databases, load balancers) across multiple cloud providers with a single workflow and state model.
When Ansible wins: configuring software on already-running servers (installing packages, writing config files, restarting services) — Terraform deliberately avoids this scope.
They are complementary: Terraform creates the infrastructure, Ansible configures what runs on it.
Terraform's Core Value Proposition
1. Provider-agnostic
Terraform has providers for 3,000+ services — AWS, Azure, GCP, Kubernetes, Datadog, GitHub, PagerDuty, Vault, and more. One workflow, one CLI, one state model for all of them.
# Single config, three clouds
resource "aws_instance" "web" { ... } # AWS
resource "azurerm_linux_virtual_machine" "app" { ... } # Azure
resource "google_compute_instance" "db" { ... } # GCP
2. State as the source of truth
Terraform's state file maps your config to real infrastructure. This enables:
- Plan preview: show exactly what will change before changing it
- Drift detection: find infrastructure that changed outside Terraform
- Dependency graph: determine safe creation/deletion order automatically
3. Execution plan
terraform plan shows a diff before any changes are made:
Plan: 2 to add, 1 to change, 0 to destroy.
+ aws_instance.web (new)
+ aws_security_group.web_sg (new)
~ aws_s3_bucket.assets — tags updated
No other IaC tool makes the "what will change" answer this explicit before committing.
4. Dependency graph
Terraform builds a DAG (directed acyclic graph) of resource dependencies and applies changes in parallel where possible. Resources with depends_on or implicit references are applied in the correct order automatically.
flowchart LR
VPC --> Subnet
VPC --> SecurityGroup
Subnet --> EC2
SecurityGroup --> EC2
EC2 --> ElasticIP
Terraform creates VPC and builds the graph — Subnet and SecurityGroup are created in parallel, then EC2 waits for both.
Terraform vs Manual Infrastructure
| Manual (Console/CLI) | Terraform | |
|---|---|---|
| Reproducible | ❌ Click-ops is not repeatable | ✅ Same config → same infra |
| Version controlled | ❌ No history of what changed | ✅ Git diff shows every change |
| Testable | ❌ Hard to validate | ✅ terraform validate, plan preview |
| Auditable | ❌ CloudTrail only shows who clicked | ✅ PR review before any change |
| Multi-environment | ❌ Manual duplication | ✅ Workspaces + variable files |
| Disaster recovery | ❌ Rebuild from memory | ✅ terraform apply rebuilds everything |
Key Terms
| Term | Definition |
|---|---|
| HCL | HashiCorp Configuration Language — the declarative language Terraform configs are written in |
| Provider | Plugin that translates Terraform resources to API calls for a specific platform |
| Resource | A single infrastructure object managed by Terraform (EC2 instance, S3 bucket, etc.) |
| State | JSON file recording the real-world resource IDs that correspond to your config |
| Plan | A preview of changes Terraform will make — read-only, no side effects |
| Apply | Execute the plan — make the actual API calls to create/update/delete |
| Module | A reusable group of resources packaged together |
| Workspace | Separate state files within the same config — used for environment isolation |
Related Posts
- Terraform Basics: Providers, Resources, and Initialization — the hands-on mechanics: HCL block types, providers, resources, and the
terraform init→plan→applycommands - Terraform Core Workflow & Commands — the Write → Plan → Apply cycle in detail, with the production CI pattern
- TF State & Backend Management — how the state file works, remote backends, and why state is central to everything Terraform does
