Quick Answer

Terraform describes infrastructure in configuration files and creates it through provider APIs. It records what it built in a state file, compares that to your configuration, and applies the difference. Never edit or lose the state file.

The problem with clicking

You create a server, a database and a load balancer through a cloud console. Everything works. Three months later:

  • Nobody remembers why a particular firewall rule exists, so nobody dares remove it.
  • You need an identical staging environment and must reproduce it from memory. It is not identical.
  • Someone changed a setting and nobody knows who, when, or what it was before.
  • An account is deleted and the environment cannot be rebuilt.

Infrastructure as code fixes all four by making the configuration a file. It goes in git, so it is reviewed, has history, and can be recreated exactly. "Why does this rule exist?" is answered by git blame.

The secondary benefit is that environments genuinely match. Most "works in staging, fails in production" problems are configuration drift, and drift is what code prevents.

What the configuration looks like

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_s3_bucket" "uploads" {
  bucket = "myapp-uploads-${var.environment}"
}

output "bucket_name" {
  value = aws_s3_bucket.uploads.id
}

Declarative, like Kubernetes manifests: you describe what should exist rather than the steps to create it.

Resources can reference each other, and Terraform works out the dependency order automatically — a server referencing a security group is created after it, without you specifying that.

The same configuration with different variable values produces staging and production, which is the practical benefit that sells it.

The workflow

terraform init      # download providers
terraform plan      # show what would change
terraform apply     # make it so
terraform destroy   # remove everything it created

plan is the reason people trust Terraform. It compares your configuration against reality and prints exactly what it will add, change or destroy, before touching anything.

Reading that output carefully is a habit worth building, and the word to watch for is destroy. Some changes cannot be applied in place — renaming certain resources means deleting and recreating them, which on a database means losing it. Terraform tells you, in the plan, and people approve without reading.

In a team, run plan in CI on every pull request so reviewers see the infrastructure change alongside the code change.

destroy is genuinely useful for students: build an environment, experiment, and tear it down completely so nothing keeps billing.

State: the thing that causes real trouble

Terraform records what it created in a state file mapping your configuration to actual resource IDs. Without it, Terraform cannot tell whether a resource in your config already exists or needs creating.

Four rules follow, and violating them causes most Terraform incidents:

  • Never edit it by hand. It is generated. Use terraform state commands if you must manipulate it.
  • Never commit it to git. It contains resource details and frequently secrets in plain text — database passwords included.
  • Store it remotely with locking for any shared use — an S3 bucket with DynamoDB locking, or Terraform Cloud. Two people running apply against a local state file simultaneously will corrupt it.
  • Do not lose it. Losing state means Terraform no longer knows it owns anything and will try to create duplicates of everything.

The related trap: changing infrastructure by hand after Terraform created it. The next plan sees the difference and offers to revert your manual change. Once infrastructure is managed by Terraform, manage it only through Terraform.

Practical guidance

  • Start small. Put one existing thing under Terraform rather than converting everything at once. terraform import brings existing resources into state.
  • Use modules to package a reusable group of resources, so a standard environment is one module call rather than copied blocks.
  • Pin provider versions. An unpinned provider can change behaviour between runs, which is exactly what infrastructure as code exists to prevent.
  • Keep secrets out. Reference a secrets manager rather than writing values into .tf files, which are committed.
  • Separate environments into different state files, so a mistake in staging cannot touch production.

For students, Terraform is worth a weekend. Defining a small environment, applying it, and destroying it teaches the cloud services involved and demonstrates a practice most graduates have never touched — which makes it genuinely notable in an interview.

Frequently Asked Questions

What is the Terraform state file? A record mapping your configuration to real resource IDs. Terraform needs it to know what it already created, which is why losing it makes Terraform try to recreate everything.
Should I commit the state file to git? No. It often contains secrets in plain text, and concurrent access corrupts it. Use remote state with locking, such as S3 with DynamoDB.
What happens if I change infrastructure manually? The next plan detects the drift and offers to revert it to match your configuration. Once a resource is managed by Terraform, change it only through Terraform.
What does terraform plan do? It compares your configuration with actual infrastructure and prints exactly what would be added, changed or destroyed, without applying anything. Always read it, especially for destroy actions.
Is Terraform tied to AWS? No. It uses providers for AWS, Azure, Google Cloud and many other services. The configuration language is the same, though resource definitions differ per provider.