Terraform Hands-On Guide: State, Modules, Workspaces & Real AWS Examples
Terraform is the dominant Infrastructure as Code tool in the industry. I use Terraform daily in production to provision and manage AWS infrastructure — VPCs, EKS clusters, RDS databases, ALBs, and IAM roles. This guide covers everything from the basic plan-apply workflow to production-grade module design, with real AWS examples you can use immediately.
How Terraform Works — The Core Model
Terraform uses a declarative model: you describe the desired end state of your infrastructure in HCL (HashiCorp Configuration Language), and Terraform figures out how to get there. It maintains a state file that maps your HCL declarations to real resources in the cloud. On each run, Terraform compares your HCL (desired state) against the state file (last-known actual state) and plans the changes needed to reconcile them.
1.
terraform init — Download providers, initialise backend2.
terraform plan — Preview what will change (no changes applied)3.
terraform apply — Apply the planned changes to real infrastructure
Terraform State — The Most Important Concept
The state file (terraform.tfstate) is the most critical component of any Terraform setup.
It is the source of truth mapping your HCL resource declarations to actual cloud resources (EC2 instance
IDs, RDS endpoint URLs, etc.). Without the state file, Terraform cannot know what already exists and
would try to create everything from scratch.
By default, state is stored locally as a JSON file. This is fine for solo learning but catastrophic
in teams: two engineers running terraform apply simultaneously can corrupt the state,
and local state means the team cannot share infrastructure management.
Remote State with S3 + DynamoDB
For every team environment, always use remote state. The standard AWS setup is S3 for storage and DynamoDB for state locking:
The DynamoDB lock table prevents two engineers from running terraform apply simultaneously.
When any state-modifying operation starts, Terraform writes a lock record to DynamoDB. If another
operation finds an existing lock, it waits or errors. This prevents race conditions that can corrupt state.
Real AWS Infrastructure Example — VPC + EKS
Modules — Building Reusable Infrastructure
Modules are the primary mechanism for reuse in Terraform. A module is just a directory of
.tf files with defined input variables and output values. You can create internal modules
for your organisation's standard patterns, or use published modules from the Terraform Registry.
Workspaces vs Directory Structure for Environments
Terraform workspaces allow multiple state files from the same configuration directory. The common pattern: use workspaces for identical environments (same infra, different sizing/counts). Use separate directories for structurally different environments (staging might not have some services).
In practice, most teams use separate directories per environment (environments/staging/,
environments/production/) with shared modules. This provides better isolation — a broken
production apply cannot affect staging state.
Interview Q&A
terraform import, resource by resource. Enable S3 versioning and never allow state files to be deleted. This is why S3 bucket deletion protection for the state bucket is mandatory.terraform import aws_instance.my_instance i-1234567890abcdef0. Terraform reads the real resource from AWS and writes its state to the state file. The HCL must match the actual resource configuration exactly, or the next plan will show a diff. For large existing infrastructures, tools like terraformer can auto-generate both the HCL and the import commands by scanning your AWS account.terraform taint marks a resource for replacement on the next apply (deprecated in Terraform 0.15.2). The modern equivalent is terraform apply -replace="aws_instance.my_instance". Both force destruction and recreation of a specific resource, even if its configuration has not changed. Use when a resource has entered a broken state that Terraform cannot detect from configuration alone — for example, an EC2 instance with a corrupted OS or a broken Kubernetes node.🗂️ Explore Terraform on the Interactive Mind Map
See how Terraform connects to AWS, Azure, Kubernetes, Ansible, and Vault — with real commands and interview Q&A.
Open Interactive Mind Map ← CI/CD GuideTerraform provisions the infrastructure — CI/CD pipelines deploy to it. Learn how to wire everything together with GitHub Actions & ArgoCD →
📩 Get Free DevOps Interview Notes
Cheat sheets, real commands, interview Q&As — free.
No spam · Follow @master.devops for daily tips
Terraform State — The Complete Picture
Terraform state is the most important concept in infrastructure-as-code. Every terraform plan
compares three things: your HCL files, real cloud infrastructure, and the state file. Misunderstanding
state is the root cause of most production Terraform incidents.
Modules — Reusable Infrastructure
Modules encapsulate a complete logical component (VPC, EKS cluster, RDS instance) with configurable inputs and useful outputs. Most mature DevOps teams maintain an internal module registry.
Workspaces vs Separate Directories
| Approach | When to use | Limitation |
|---|---|---|
| Workspaces | Identical infra, different environments | Hard to have environment-specific config |
| Separate dirs | Environments with significant config differences | Code duplication without shared modules |
| Terragrunt | Large organisations needing DRY multi-env IaC | Adds tool dependency and learning curve |
Terraform Interview Questions & Answers
terraform import resource_type.resource_name cloud_resource_id. Example: terraform import aws_instance.web i-0abc1234. This adds the existing resource to state. Important: import only adds to state — you must also write the HCL configuration manually that matches the imported resource, then run terraform plan to verify no unintended changes are planned. Terraform 1.5+ added import blocks in HCL that can generate configuration automatically.aws_secretsmanager_secret or vault_generic_secret data sources rather than storing values directly. Mark sensitive variables and outputs with sensitive = true to prevent them appearing in plan output. Use server-side encryption on the remote backend. Consider SOPS for encrypting sensitive tfvars files in version control.resource block) create, update, and delete infrastructure — Terraform manages their lifecycle. Data sources (data block) read existing infrastructure that Terraform does not manage — they are read-only lookups. Example: you might use a data source to look up a VPC ID by tag name (data "aws_vpc" "existing") and then pass it as input to a resource you are creating. Data sources are re-evaluated on every plan; resources are only changed when their configuration changes.