Terraform Lesson 2 – Why Infrastructure as Code Matters | Dataplexa
Section I · Lesson 2

Why Infrastructure as Code Matters

Knowing what Terraform is and knowing why it exists are two different things. This lesson is about the second one — and it changes how you think about infrastructure permanently.

This lesson covers

What teams looked like before IaC → The six problems IaC solves directly → How infrastructure in Git changes everything → The difference between mutable and immutable infrastructure → Why IaC is now a professional standard, not an optional tool

Before IaC Existed

Picture a mid-sized engineering team in 2012. They have a production environment on AWS. One senior engineer — call him Marcus — built it. He knows every setting, every security group rule, every subnet configuration. That knowledge lives entirely in his head.

Marcus goes on holiday for two weeks. A server fails. Nobody else on the team knows how to recreate it correctly. They spend three days guessing their way through the AWS console, getting things mostly right, missing a few settings they cannot see because they were never written down.

Marcus returns and finds a production environment that looks right on the surface but behaves slightly differently from what he built. Nobody knows exactly what changed. The team has what engineers call a snowflake server — a piece of infrastructure so unique and hand-crafted that nobody fully understands it and nobody dares touch it.

The Analogy

A snowflake server is exactly what it sounds like — completely unique, impossible to reproduce, and it melts under pressure. Infrastructure as Code replaces snowflakes with stamped parts. Every environment is built from the same mould. If one breaks, you throw it away and stamp a new one. No heroics. No guesswork.

The Six Problems IaC Solves

Infrastructure as Code was not invented to be elegant. It was invented because teams kept hitting the same painful problems over and over. Here are the six that matter most:

Problem Without IaC With IaC
Reproducibility Every environment is different Same code, identical environments
Knowledge sharing Lives in one person's head Lives in the codebase, owned by the team
Change tracking No record of what changed or when Every change is a Git commit
Disaster recovery Rebuild from memory — takes days Run terraform apply — takes minutes
Environment drift Dev and prod diverge silently All environments built from same source
Cost control Forgotten resources run forever terraform destroy cleans up instantly

Infrastructure in Git — Why It Changes Everything

The moment your infrastructure lives in .tf files stored in a Git repository, it inherits everything that makes application code manageable at scale.

Full audit trail

Every infrastructure change is a commit. Who changed it, what they changed, when they changed it, and why — all of it is in the Git log. Compliance teams love this. Incident responders love this. It answers the question "what changed before this broke?" in seconds.

Code review for infrastructure

Before a change goes to production, it goes through a pull request. A senior engineer reviews it. They catch the misconfigured security group before it opens port 22 to the world. IaC turns infrastructure changes into a reviewable, discussable, approvable process — the same discipline that makes application code reliable.

Rollback in seconds

A bad infrastructure change goes to production. Without IaC, you spend an hour manually undoing whatever was clicked. With IaC, you revert the Git commit and run terraform apply. The previous state of your infrastructure is restored in minutes, not hours.

Branching for infrastructure experiments

Need to test a new network architecture without touching production? Create a Git branch, modify the configuration, apply it to a test environment. If it works, merge. If it does not, delete the branch and destroy the test environment. Zero risk to production. Zero manual cleanup.

Mutable vs Immutable Infrastructure

This is one of the most important mindset shifts IaC introduces. Understanding it now will save you from a category of infrastructure problems that trips up most teams at least once.

Mutable infrastructure means you take an existing server and modify it in place — SSH in, install a package, change a config file, restart a service. The server's history accumulates. Nobody knows exactly what state it is in after months of patches and changes. This is the snowflake problem again.

Mutable Infrastructure Server v1 Original state patch Same server Modified patch Same server Unknown state History accumulates. State becomes unknown. Immutable Infrastructure Server v1 Known state new config Server v2 Fresh. Known state. Old server destroyed. New one built clean.

Immutable infrastructure means you never modify a running server. When something needs to change, you build a new server from updated configuration and replace the old one. The new server's state is completely known — it was built from code, from scratch, with no accumulated history.

Terraform encourages immutable thinking. When you update a resource in your configuration and apply, Terraform often destroys the old resource and creates a new one rather than patching what is already there. This feels uncomfortable at first. Over time you realise it is the only approach that keeps infrastructure predictable at scale.

What This Looks Like in Practice

Here is the same infrastructure task done two ways — the old manual way versus the IaC way. The task: create an S3 bucket in AWS for storing application logs.

New terms:

  • aws_s3_bucket — the Terraform resource type for an Amazon S3 storage bucket.
  • aws_s3_bucket_versioning — a separate resource that enables versioning on an S3 bucket. In AWS, bucket settings like versioning, encryption, and access control are managed as separate API resources — and Terraform mirrors this exactly.
  • bucket argument — the globally unique name for the S3 bucket. No two S3 buckets in the world can share a name.
  • versioning_configuration status — either "Enabled" or "Suspended". When enabled, S3 keeps every version of every object — useful for audit trails and accidental deletion recovery.
# main.tf — Create an S3 bucket for application logs

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "app_logs" {
  bucket = "acme-app-logs-prod"

  tags = {
    Name        = "Application Logs"
    Environment = "prod"
    ManagedBy   = "Terraform"
  }
}

# Enable versioning so deleted logs can be recovered
resource "aws_s3_bucket_versioning" "app_logs_versioning" {
  bucket = aws_s3_bucket.app_logs.id

  versioning_configuration {
    status = "Enabled"
  }
}

Compare this to the manual approach: Log into AWS console. Navigate to S3. Click "Create bucket". Fill in the name. Choose the region. Toggle versioning on. Add tags one by one. Click confirm. Now do that again for staging. And again for dev. And again when a new region is needed. And again when a new team member needs to set up their own environment. With Terraform, all of that is one command.

$ terraform apply

Terraform will perform the following actions:

  # aws_s3_bucket.app_logs will be created
  + resource "aws_s3_bucket" "app_logs" {
      + bucket = "acme-app-logs-prod"
      + tags   = {
          + "Environment" = "prod"
          + "ManagedBy"   = "Terraform"
          + "Name"        = "Application Logs"
        }
    }

  # aws_s3_bucket_versioning.app_logs_versioning will be created
  + resource "aws_s3_bucket_versioning" "app_logs_versioning" {
      + bucket = "acme-app-logs-prod"
      + versioning_configuration {
          + status = "Enabled"
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.

  Enter a value: yes

aws_s3_bucket.app_logs: Creating...
aws_s3_bucket.app_logs: Creation complete after 3s [id=acme-app-logs-prod]
aws_s3_bucket_versioning.app_logs_versioning: Creating...
aws_s3_bucket_versioning.app_logs_versioning: Creation complete after 1s

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

What just happened?

  • Two resources were created in one apply. The bucket first, then versioning — because versioning depends on the bucket existing. Terraform automatically works out the correct order using its dependency graph.
  • The versioning resource references the bucket. aws_s3_bucket.app_logs.id reads the bucket ID from the state file after it is created and passes it to the versioning resource. This is how Terraform wires resources together — no hardcoding IDs.
  • Run this same configuration in staging by changing the bucket name variable. Identical setup. Zero extra effort. Zero chance of forgetting the versioning step.

Common Mistakes

Treating IaC as documentation rather than the source of truth

Some teams write Terraform configurations to document infrastructure that was actually built manually. The configs and the real infrastructure slowly diverge. When someone runs terraform apply, chaos follows. IaC only works when it is the only way infrastructure gets built — not a record of what was clicked somewhere else.

Storing Terraform configurations outside version control

Keeping .tf files on a local machine or a shared drive defeats the entire purpose. Without Git, you lose the audit trail, the ability to review changes, and the ability to roll back. Every Terraform project belongs in a version-controlled repository from day one.

Applying changes directly to production without reviewing the plan

IaC does not make infrastructure changes safe automatically. It makes them reviewable. The safety comes from the process — plan reviewed, pull request approved, applied to staging first, then production. Teams that skip these steps with Terraform have exactly the same incidents as teams with no IaC at all.

The mindset shift that matters most

Stop thinking of infrastructure as something you configure. Start thinking of it as something you declare. You are not telling a system what to do — you are describing what should exist. That shift in thinking is what makes IaC work at scale, and it is what separates engineers who use Terraform confidently from those who use it as a more complicated way of clicking through a console.

Practice Questions

1. What term describes a server that has been modified so many times manually that nobody fully understands its state anymore?



2. When a server needs to be updated, IaC encourages destroying the old one and building a fresh replacement from updated configuration. What type of infrastructure approach is this called?



3. What version control system should every Terraform project be stored in from day one?



Quiz

1. What does storing Terraform configurations in Git give you that manual infrastructure management cannot?


2. For IaC to work correctly, how should it be used within a team?


3. In an immutable infrastructure approach, how do you update a server?


Up Next · Lesson 3

Terraform vs CloudFormation vs ARM

Terraform is not the only IaC tool. AWS has CloudFormation. Azure has ARM. So why did the industry pick Terraform? The answer is more interesting than you might think.