In this post, we’ll take an in-depth look at Terraform, the leading platform in Infrastructure as Code (IaC).
Over the past few years, cloud computing has become ubiquitous, fundamentally changing how we manage infrastructure. In the past, setting up servers meant physically going to data centers, installing hardware, and connecting cables. With the emergence of cloud providers like AWS, Azure, and GCP, we can now spin up servers with just a few clicks.
However, this convenience introduces a new challenge. As services grow and you need to manage dozens or hundreds of resources, manually clicking through console interfaces becomes inefficient and error-prone. This is where Infrastructure as Code (IaC) comes in, with Terraform as its leading solution.
Today, we’ll explore what Terraform is, why so many development teams use it, and how you can get started.
1. What is Terraform?
Terraform is an open-source infrastructure automation tool developed by HashiCorp. Simply put, it lets you write and manage cloud infrastructure as code. In February 2025, IBM acquired HashiCorp, bringing increased attention to Terraform’s future direction.
Let’s look at an example. Suppose you want to create an EC2 instance on AWS. Typically, you’d log into the AWS Management Console, navigate to the EC2 menu, click Launch Instance, select an instance type, configure Security Groups, and so on. With Terraform, you can express this entire process in just a few lines of code:
resource "aws_instance" "my_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "MyWebServer"
}
}
When you run this code, Terraform automatically communicates with AWS and creates the server for you.
2. Why Use Terraform?
You might wonder, “Why write code when I can just click in the console?” That’s a fair question, but Terraform offers significant advantages.
Version Control for Infrastructure
Infrastructure written as code can be managed with version control systems like Git. Every change is recorded with commit history, and you can roll back to previous versions if issues arise. You manage infrastructure just like you manage source code.
Reduce Human Error
Manual console operations are prone to misconfiguration and missed settings. With code, team members can catch mistakes through code reviews, and you maintain consistency when reusing configurations.
Replicate Environments Quickly
Need to set up development, staging, and production environments? Manual console work is time-consuming and can lead to subtle differences between environments. With Terraform code, you can deploy identical configurations across multiple environments by simply changing variables.
Manage Multiple Clouds from One Tool
Terraform supports not just AWS, Azure, and GCP, but also Kubernetes, Docker, GitHub, and many other platforms. Managing multiple clouds with a single tool is a significant advantage, often called multi-cloud management.
Measurable Impact
According to Puppet’s 2016 DevOps Report, teams that adopted IaC saw:
- Deployment frequency increased by 200x
- Recovery time reduced by 24x
- Lead time from development to production decreased by 2,000x
While not every team will see such dramatic results, the productivity gains from automation are undeniable.
3. How Does Terraform Work?
Understanding Terraform’s operating principles helps you use it more effectively. Terraform fundamentally operates in a declarative manner.
Declarative vs Procedural
Aspect | Procedural | Declarative |
---|---|---|
Approach | Define “how” with step-by-step commands | Define “what” desired state |
Example | “Create VPC, then subnet, then routing table” | “Final state with VPC and subnet” |
Advantage | Fine-grained control | Concise and easier to understand |
Disadvantage | Verbose and complex code | Internal operations less transparent |
Procedural approaches give step-by-step instructions like “create A, then B, then C.” Declarative approaches define the desired end state, and Terraform figures out the steps needed to achieve it.
Terraform Core Components
Provider Cloud providers like AWS, GCP, and Azure are called Providers. Terraform communicates with these providers via APIs to create and manage resources. The Terraform Registry hosts over 4,000 providers.
Resource The actual infrastructure components you create are Resources. EC2 instances, load balancers, RDS databases, and more all qualify as resources.
State File Terraform records the current state of deployed infrastructure in a JSON file called terraform.tfstate
. This file lets Terraform identify differences between your code and actual infrastructure, determining what changes are needed.
HCL (HashiCorp Configuration Language) Terraform configuration files are written in HCL, a purpose-built language using the .tf
file extension. HCL is readable and straightforward, making it accessible for newcomers.
Module Modules are collections of commonly used infrastructure code packaged for reuse, similar to functions or libraries in programming.
4. Terraform Basic Workflow
Infrastructure management with Terraform typically follows the lifecycle: init → plan → apply → destroy. Let’s examine each step.
terraform init (Initialize)
The first command you run when starting a project. Init downloads necessary provider plugins and initializes your project.
terraform init
This creates a .terraform
directory and records provider version information in .terraform.lock.hcl
for tracking changes.
terraform plan (Preview Changes)
The plan command shows what changes will occur before actually applying your code. It’s like running a simulation.
terraform plan
Output appears in this format:
Plan: 1 to add, 0 to change, 0 to destroy.
+
symbol: Resources to be created~
symbol: Resources to be modified-
symbol: Resources to be destroyed
This step makes no actual infrastructure changes, so you can safely review the results. You can also save the plan to a file:
terraform plan -out=tfplan
terraform apply (Execute Changes)
Once you’ve confirmed the plan looks correct, the apply command creates or modifies infrastructure.
terraform apply
Terraform prompts for confirmation. Type “yes” to proceed with resource creation. After apply completes, the state file updates.
For automated approval (useful in CI/CD):
terraform apply -auto-approve
terraform destroy (Remove Resources)
Use this command to delete resources you no longer need.
terraform destroy
This deletes all resources managed by Terraform, so use it carefully! Exercise extra caution in production environments.
5. Installing and Getting Started with Terraform
Let’s install Terraform and create a simple example project.
Installation Methods
Mac Users
Install easily with Homebrew:
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
For version management, use tfenv:
brew install tfenv
tfenv install 1.9.0
tfenv use 1.9.0
Windows Users
Use Chocolatey:
choco install terraform
Or download directly from the Terraform installation page.
Linux Users (Ubuntu/Debian)
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
Verify Installation
Confirm successful installation:
terraform version
You should see version information like:
Terraform v1.9.0
on darwin_arm64
Your First Terraform Project
Let’s create a simple project. We’ll use AWS as an example, but other clouds work similarly.
Prerequisites: AWS Account and Authentication
You’ll need AWS Access Key and Secret Key. Generate these in AWS Console → IAM → Users → Security credentials.
Set as environment variables:
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
A more secure method is installing AWS CLI and configuring credentials with aws configure
.
Step 1: Create Project Directory
mkdir my-first-terraform
cd my-first-terraform
Step 2: Write Provider Configuration
Create provider.tf
to configure the AWS Provider:
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1" # North Virginia region
}
Step 3: Define Resources
Create main.tf
to define a simple VPC:
# Create VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "my-terraform-vpc"
}
}
# Create subnet
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
tags = {
Name = "my-terraform-subnet"
}
}
# Output VPC ID
output "vpc_id" {
description = "The ID of the VPC"
value = aws_vpc.main.id
}
Step 4: Initialize and Execute
# Initialize
terraform init
# Format check
terraform fmt
# Validation
terraform validate
# Preview changes
terraform plan
# Apply changes
terraform apply
Congratulations! You’ve successfully executed your first Terraform project. Check the AWS Console → VPC Dashboard to see your newly created VPC and subnet.
Clean Up
When testing is complete, delete resources:
terraform destroy
6. Best Practices and Tips
State File Management is Critical
The terraform.tfstate
file contains all information about your infrastructure, including sensitive data like passwords and access keys. Therefore:
- Don’t commit to Git! Add to
.gitignore
- Store in remote backend like AWS S3
- Enable encryption for state files
Remote backend configuration example:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "terraform.tfstate"
region = "us-east-1"
encrypt = true
}
}
Make Planning a Habit
Always run plan before apply to preview changes. This catches unexpected modifications or deletions. This practice is especially critical in production environments.
Use Modules
For repeated configurations, create modules for reusability, similar to functions in programming.
Example:
module "vpc" {
source = "./modules/vpc"
vpc_cidr = "10.0.0.0/16"
vpc_name = "production-vpc"
}
Avoid Manual Console Changes
Don’t directly modify Terraform-managed resources in the console. Manual changes cause drift between the state file and actual infrastructure.
If manual changes are unavoidable, sync the state with terraform refresh
or import existing resources with terraform import
.
Keep Projects Small
Rather than one massive Terraform project, divide into smaller units like MSA (Microservice Architecture). Separate network, database, and application concerns for:
- Limited blast radius of changes
- Easier testing
- Better team collaboration
7. Current State of Terraform (Late 2025)
IBM’s HashiCorp Acquisition
In February 2025, IBM acquired HashiCorp for $6.4 billion. This has generated interest in Terraform’s future direction, with expectations for enhanced enterprise support.
License Change and OpenTofu
In 2023, HashiCorp changed Terraform’s license from MPL 2.0 to BUSL 1.1 (Business Source License). In response, the community launched OpenTofu, an open-source fork now under the Linux Foundation’s CNCF.
Terraform vs OpenTofu Comparison
Aspect | Terraform | OpenTofu |
---|---|---|
License | BUSL 1.1 | MPL 2.0 (fully open source) |
Governance | HashiCorp (IBM) | Linux Foundation |
Commercial Services | Restricted | Unrestricted |
Feature Compatibility | Original | Fork from v1.5.6 |
Community | Mature | Growing |
For most users, these changes have minimal impact, but it’s worth monitoring OpenTofu long-term. OpenTofu operates nearly identically to Terraform and supports existing Terraform code.
Terraform Alternatives
Beyond Terraform, several IaC tools exist:
- Pulumi: Uses general programming languages like TypeScript, Python
- AWS CDK: AWS-specific, written in programming languages
- Crossplane: Kubernetes-native IaC
- Ansible: Specialized for configuration management
Each tool has trade-offs, so choose based on your project requirements.
What is ‘OpenTofu’? Open-Source Terraform Alternative for IaC
8. Real-World Use Cases
Case 1: Multi-Region Deployment
Deploying identical infrastructure across regions:
variable "regions" {
default = ["us-east-1", "us-west-2", "eu-west-1"]
}
module "vpc" {
for_each = toset(var.regions)
source = "./modules/vpc"
region = each.value
}
Case 2: Environment-Specific Configuration
Separating dev/staging/production settings:
# dev.tfvars
environment = "dev"
instance_type = "t2.micro"
# prod.tfvars
environment = "prod"
instance_type = "t3.large"
Execute with:
terraform apply -var-file="dev.tfvars"
terraform apply -var-file="prod.tfvars"
Case 3: Conditional Resource Creation
variable "create_database" {
type = bool
default = false
}
resource "aws_db_instance" "this" {
count = var.create_database ? 1 : 0
# ... configuration
}
9. Troubleshooting Tips
When Plan and Apply Results Differ
Sometimes plan shows no issues but apply fails. Common causes:
- Duplicate resource names
- Insufficient permissions
- Dependency problems
Debug with:
# Enable verbose logging
export TF_LOG=DEBUG
terraform apply
When State File Gets Corrupted
# Refresh state
terraform refresh
# List state resources
terraform state list
# Remove specific resource
terraform state rm aws_instance.example
Importing Existing Resources
To manage console-created resources with Terraform:
# 1. Write resource definition
# Define resource in main.tf
# 2. Import resource
terraform import aws_instance.example i-1234567890abcdef0
# 3. Verify with plan
terraform plan
10. Learning Resources
Official Documentation and Tutorials
- Terraform Official Documentation – Most accurate and current information
- Terraform Registry – Search providers and modules
- HashiCorp Learn – Step-by-step tutorials
- Terraform AWS Getting Started – AWS beginner guide
Community and Forums
- Terraform Official Forum
- Reddit r/Terraform
- Various DevOps communities and blogs
Recommended Books
- “Terraform: Up & Running” by Yevgeniy Brikman
- “Terraform in Action” by Scott Winkler
Practice Environments
- Terraform Cloud – Free tier available
- LocalStack – Test AWS locally
Terraform may seem challenging at first with its new concepts and commands. However, once you understand the basic workflow and start with simple examples, you’ll find it surprisingly accessible.
The key is not trying to master everything before starting. Begin with small projects and build experience through hands-on practice. You’ll make mistakes and encounter errors, but that’s how you develop deeper understanding.
Managing infrastructure as code means more than just learning a new tool. It transforms development practices, improves team collaboration, and ultimately enables more stable and efficient systems. Many organizations report significant reductions in infrastructure management time, faster deployments, and fewer errors after adopting Terraform. While there’s a learning curve, the investment is worthwhile.
When you have questions, leverage the official documentation and community extensively. Other developers’ experiences can be invaluable. 🙂