TL;DR
Terraform is an infrastructure-as-code (IaC) tool that lets you declare the cloud resources you want (networks, servers, databases, DNS, Kubernetes, etc.), then plans and applies the minimal changes to reach that desired state—reliably and repeatably.
What is infrastructure-as-code (IaC)?
In DevOps, Infrastructure as Code (IaC) is the practice of managing and provisioning IT infrastructure (servers, networks, databases, etc.) through machine-readable definition files and code, rather than manual processes or interactive tools. This allows teams to automate infrastructure setup, ensure consistency across environments, and manage configurations like software code – enabling faster, more reliable application delivery and deployment.
Why bother with Terraform?
Without IaC, cloud environments drift over time: manual clicks, forgotten changes, and ad-hoc fixes stack up. Terraform solves that by giving you:
- Repeatability: the same code builds identical environments (dev/test/prod).
- Speed: one command provisions complex stacks in minutes.
- Safety: see exactly what will change before you approve it.
- Collaboration: code reviews, version control, and audit history.
- Portability: thousands of providers, from AWS/Azure/GCP to SaaS (Cloudflare, Datadog, GitHub, etc.).
- Governance: enforce tagging, naming, and guardrails via modules and policy.
A quick mental model
Think of Terraform as a sat-nav for your infrastructure:
You write a map (HCL files) → Terraform calculates a route (plan)
→ Terraform drives the changes (apply)
→ Terraform remembers where you parked (state)- HCL: HashiCorp Configuration Language, a tidy, readable DSL.
- Providers: plugins that know how to talk to an API (AWS, Azure, GCP, Kubernetes, GitHub, Cloudflare, …).
- Resources: the things you create/manage (buckets, VMs, VPCs, DNS records).
- Data sources: read-only lookups (e.g., get latest AMI ID).
- Modules: reusable building blocks (your internal “lego bricks”).
- State: a snapshot of what exists; used to plan safe, minimal changes.
- Backends: where state is stored (e.g., S3 + DynamoDB lock, Azure Storage, GCS).
How Terraform actually works (high level)
-
Write: describe the desired infrastructure in .tf files.
-
Initialise: install the required providers (terraform init).
-
Plan: preview changes (terraform plan)—add, update, destroy.
-
Apply: execute the plan (terraform apply).
-
Store State: track what was created (ideally in a remote backend with locking).
-
Iterate: change code → plan → apply. Terraform handles the drift and diffs.
Here is a tiny example:
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
provider "aws" {
region = var.region
}
variable "region" { default = "eu-west-2" } # London
resource "aws_s3_bucket" "assets" {
bucket = "my-blog-assets-unique-name"
tags = {
app = "blog"
env = "dev"
}
}
output "bucket_name" {
value = aws_s3_bucket.assets.bucket
}Let me explain what those code does step by step:
Step 1: Shift from “clicks” to “code” - Treat infrastructure as code sitting in Git. You review it, test it, and roll it back like software.
Step 2: Model your stack as resources - Break the system into resources (network, compute, databases, DNS, certificates). Each becomes a small, testable block.
Step 3: Reuse via modules - Wrap common patterns (e.g., vpc, eks_cluster, static_website) into modules with sensible variables and outputs. This standardises naming, tagging, and security.
Step 4: Separate environments - Use the same modules with different variables (dev/test/stage/prod). Keep state isolated per environment. Promote changes through environments via pull requests.
Step 5: Store state remotely with locking - Choose a backend with locking (e.g., S3+DynamoDB, Azure Blob, GCS). This prevents two people from applying at once and corrupting state.
Step 6: Add guardrails -Introduce policy and validation: required tags, naming conventions, restricted instance types, allowed regions. Do this in modules and (optionally) policy-as-code tools.
Real-world use cases (with “what you’d actually manage”)
-
Foundations in a single cloud
-
You build: VPC/VNet + subnets, routing, firewalls, IAM roles, security groups.
-
Why Terraform? Consistent networking across all environments, zero manual drift.
-
-
Static website or blog hosting
-
You build: S3/Blob/GCS bucket for assets, CDN (CloudFront/Azure CDN), DNS (Route53/Cloudflare).
-
Value: One command to deploy the whole front door of your site, reproducibly.
-
-
Kubernetes platform
-
You build: Managed cluster (EKS/AKS/GKE), node groups, IAM/RBAC, add-ons (Ingress, DNS, External Secrets), and app install via Helm.
-
Value: Cluster + add-ons + namespaces spun up (and torn down) consistently.
-
-
Ephemeral “Preview Environments” per PR
-
You build: A short-lived environment matching prod shape, created on each pull request and auto-destroyed on merge.
-
Value: Product managers can click around real stacks before approving.
-
-
Hybrid/multi-cloud and SaaS glue
-
You build: Cloud DNS, CDN, WAF rules, GitHub repos/teams, Datadog dashboards/alerts, PagerDuty schedules—all in one codebase.
-
Value: One place to see and control “everything”.
-
-
Data & analytics platform
-
You build: Data warehouse projects (BigQuery/Snowflake), storage buckets, IAM, scheduled jobs, secrets.
-
Value: Reproducible analytics foundations with strict access control.
-
-
Disaster recovery & region failover
-
You build: Replicated resources in a secondary region, health checks, and DNS failover.
-
Value: Documented, testable DR you can rehearse and trust.
-
-
Cost control & housekeeping
-
You build: Schedules that stop non-prod compute at night, enforce tagging for cost allocation, alert on untagged spend.
-
Value: Lower bills, cleaner reporting.
-
-
Home lab / self-hosting (bonus for tinkerers)
-
You build: Proxmox VMs, Docker hosts, local DNS, Cloudflare tunnels.
-
Value: Treat your home lab like a mini enterprise—repeatable, documented, fun.
-
What “good” Terraform looks like (habits to adopt early)
-
Readable HCL: terraform fmt + consistent naming (app_env_component).
-
Small modules with clear inputs/outputs and sensible defaults.
-
Tagged everything: env, owner, cost_centre, data_classification.
-
Remote state with locking and strict per-environment separation.
-
Plan in CI, apply with approval (e.g., plan on PR, apply on main).
-
No secrets in code: use secret managers and environment injection.
-
Drift checks: run terraform plan regularly to detect out-of-band changes.
Terraform turns “what we meant to build” into something you can prove you built—and rebuild tomorrow. Once your infrastructure is code, everything else (reviews, automation, compliance, cost control) gets easier.