Terraform & Infrastructure as Code Explained 2026 - IaC, Terraform vs CloudFormation & Config Management
A beginner's guide to Infrastructure as Code with Terraform: what IaC is and why it matters, how Terraform works across clouds, Terraform vs CloudFormation, and how configuration management fits in.
Manually clicking through cloud consoles does not scale and is impossible to reproduce. Infrastructure as Code (IaC) fixes that - and Terraform is the most popular IaC tool in DevOps.
What is Infrastructure as Code?
IaC means defining your servers, networks and cloud resources in code files instead of setting them up by hand. That code can be versioned in Git, reviewed, and re-run to produce the exact same environment every time - giving you consistency, repeatability and speed.
The test of whether a team really practises IaC is simple: if the production environment were deleted tonight, could you rebuild it from the repository? If the answer involves anyone remembering what they clicked, the answer is no.
What is Terraform?
Terraform is a cloud-agnostic IaC tool that works across AWS, Azure, GCP and many other providers. You declare the infrastructure you want, and Terraform figures out how to create, update or delete resources to match that desired state.
Declarative is the key word. You do not write "create a server". You write "there is a server, with these properties", and Terraform compares that against what exists and works out the difference. Run it twice and nothing happens the second time.
What Terraform code actually looks like
Here is a small but complete configuration - a VPC-attached EC2 instance with its security group. This is roughly the first thing you will write.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
variable "region" {
type = string
default = "ap-south-1"
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Allow HTTP in"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.al2023.id
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "web-01"
ManagedBy = "terraform"
}
}
output "public_ip" {
value = aws_instance.web.public_ip
}
Two details in there are worth internalising early. The instance references the security group as aws_security_group.web.id rather than a hardcoded ID - that reference is how Terraform works out it must create the security group first, without you specifying any ordering. And the AMI comes from a data lookup rather than a pasted ami- string, because AMI IDs differ per region and change whenever the image is rebuilt; hardcoding one is the reason a configuration that worked in Mumbai fails in Singapore.
The workflow: init, plan, apply
terraform initdownloads the providers named in your configuration. Run it once per project, and again whenever you change provider versions.terraform planshows what would change, without changing anything. It is the most important command in the tool.terraform applymakes those changes, after showing you the plan again and asking for confirmation.terraform destroytears it all down. Useful for learning environments, terrifying elsewhere.
Read every plan before applying it. Terraform expresses changes as + create, ~ update in place, and -/+ destroy and recreate. That third one is the one to watch: some attribute changes force a resource to be replaced rather than modified, and on a database that is the difference between an edit and an outage.
State - the concept that catches everyone out
Terraform records what it created in a state file. That file is how it knows the difference between "this resource does not exist yet" and "this resource exists and needs updating". Without it, Terraform cannot tell what it owns.
Three consequences follow, and they cause most beginner incidents:
- State must not live only on your laptop. If a teammate runs apply from their own machine with their own state, you will get duplicated infrastructure. Use a remote backend - an S3 bucket, Azure Storage, GCS, or Terraform Cloud.
- State must be locked. Two people applying at the same time against the same state corrupts it. S3 backends support locking so a second apply waits instead of colliding.
- State is not a secret store, but it contains secrets. Database passwords and generated keys end up in it in plain text. Never commit it to Git, and encrypt the bucket it lives in.
If someone changes infrastructure by hand in the console, Terraform's state no longer matches reality - this is drift. The next plan will try to undo their change. That is the tool working correctly, and it is also the reason teams that adopt IaC halfway have a bad time.
Modules
A module is a reusable folder of Terraform configuration - the same idea as a function. Once you have written a VPC three times, you write it once as a module with variables for the bits that differ, and call it from each environment. The public Terraform Registry has maintained modules for most common patterns, and reading a well-written one is a fast way to learn the idioms.
The usual advice is to start without modules. Write the plain resources until the repetition genuinely annoys you, then extract. Modules written before you understand the pattern tend to have the wrong variables.
Terraform vs CloudFormation vs Ansible
| Terraform | CloudFormation | Ansible | |
|---|---|---|---|
| Job | Provision infrastructure | Provision infrastructure | Configure what runs on it |
| Scope | Any cloud, one workflow | AWS only | Any machine over SSH |
| State | Explicit state file you manage | AWS tracks it for you as a stack | None - it checks and converges each run |
| Language | HCL | YAML or JSON | YAML playbooks |
Terraform and Ansible are not competitors - most teams use both. Terraform creates the servers; Ansible installs and configures what runs on them. If a question in an interview frames them as alternatives, saying so is a good answer.
Terraform vs CloudFormation
CloudFormation is AWS's native IaC service - deeply integrated with AWS but locked to it. Terraform works across every major cloud with one workflow, which is why teams running multi-cloud or wanting portability prefer it. If you are 100% on AWS forever, CloudFormation is fine; otherwise Terraform is the safer skill to learn.
How configuration management fits in
IaC tools like Terraform provision infrastructure (create the servers). Configuration management tools like Ansible then configure what runs on them (install packages, set up services) so every server stays consistent. Together they ensure environments are reproducible from scratch - no manual drift.
Mistakes that cost people their first week
- Committing
terraform.tfstateto Git. Add it to.gitignorebefore your first commit, not after. - Running
applywithout reading the plan, then discovering-/+next to a database. - Hardcoding credentials in a
.tffile. Use environment variables or the provider's own credential chain. - One giant
main.tfholding every environment, so a change to dev shows up in the production plan. Separate state per environment. - Not pinning provider versions, then finding a fresh
initpulls a new major and half the plan changes.
Industry usage
Companies use Terraform to manage cloud infrastructure across dev, staging and production reliably, making it a core, well-paid DevOps skill.
It is also one of the more interview-friendly skills to demonstrate, because a small public repository containing a working configuration and a sensible module structure proves more than any certificate does.
Related Learning Resources
Kubernetes Explained Simply 2026 - Orchestration, Networking & K8s vs Docker Swarm
Kubernetes for beginners: what it is, core concepts (pods, deployments, services, clusters), how Kubernetes networking works, and how K8s compares to Docker Swarm.
Docker Explained for Beginners 2026 - Containers, Images & Docker vs VMs
A beginner's guide to Docker: what containers are, how images and Dockerfiles work, how Docker differs from virtual machines, and how DevOps teams use Docker in CI/CD and Kubernetes.
GitOps Explained: ArgoCD, Flux and Progressive Delivery
How the reconciliation loop actually works, how Argo CD and Flux differ once you live with them, what canary and blue-green add on top, and the secrets and drift problems tutorials skip.
Ready to Start Your DevOps Career?
Join our comprehensive DevOps + GenAI course with hands-on projects, live mentorship, and placement support