What Is Infrastructure as Code?
Infrastructure as Code (IaC) is the practice of defining and managing your infrastructure — servers, networks, databases, load balancers — using machine-readable configuration files rather than manual processes or interactive tools. Those files are stored in version control, reviewed like application code, and applied automatically through pipelines.
The shift from clicking around in a cloud console to writing declarative configuration fundamentally changes how reliably you can provision and replicate environments.
Why IaC Matters
- Repeatability: the same configuration produces the same infrastructure every time, eliminating "works on my environment" problems at the infrastructure level
- Auditability: every change is tracked in git — who changed what, when, and why
- Disaster recovery: rebuild an entire environment from configuration files, not memory and runbooks
- Collaboration: infrastructure changes go through pull requests, enabling peer review before anything is applied
- Speed: provisioning environments that took days of manual work can be automated to run in minutes
Choosing Your IaC Tool
The right tool depends on your cloud provider, existing ecosystem, and team expertise:
| Tool | Approach | Best For |
|---|---|---|
| Terraform / OpenTofu | Declarative, provider-agnostic | Multi-cloud, broad ecosystem |
| AWS CloudFormation | Declarative, AWS-native | All-in on AWS |
| Pulumi | Imperative (real programming languages) | Teams who prefer code over DSLs |
| Ansible | Procedural, agentless | Configuration management, VM provisioning |
| Helm | Declarative, Kubernetes-native | Kubernetes workload management |
Terraform (and its open-source fork OpenTofu) is the most widely used for cloud provisioning. Ansible excels at configuration management and is commonly used alongside Terraform.
Core Concepts in Terraform
Providers
Providers are plugins that know how to talk to a specific API — AWS, GCP, Azure, Datadog, GitHub, and hundreds more. You declare which providers you need, and Terraform downloads them automatically.
Resources
Resources are the building blocks: an EC2 instance, an S3 bucket, a DNS record. You declare the desired state, and Terraform figures out what API calls are needed to achieve it.
State
Terraform maintains a state file that maps your configuration to real-world resources. This is what allows it to detect drift and calculate diffs. Store state remotely (S3 + DynamoDB for locking is the standard AWS pattern) — never commit state files to git.
Plan and Apply
The core workflow is: terraform plan to preview changes, then terraform apply to execute them. Always review the plan output before applying — especially in production.
Structuring Your IaC Repository
A common and effective structure separates environments and uses reusable modules:
modules/— reusable, parameterized infrastructure components (e.g., a VPC module, an ECS service module)environments/dev/— configuration for the development environmentenvironments/staging/— configuration for stagingenvironments/production/— production configuration, with stricter access controls
Each environment calls the shared modules with environment-specific variables. This avoids duplicating infrastructure definitions while keeping environment differences explicit and auditable.
IaC in Your CI/CD Pipeline
IaC should be automated through your pipeline like any other code:
- On pull request: run
terraform fmt,terraform validate, andterraform plan— post the plan output as a PR comment - On merge to main: run
terraform applyautomatically for non-production environments - For production: require manual approval of the plan before applying
Tools like Atlantis or Terraform Cloud can manage this workflow with built-in plan/apply automation and access controls.
Common Mistakes to Avoid
- Manually editing infrastructure in the console after applying IaC — this causes state drift
- Storing sensitive values (passwords, API keys) in configuration files — use a secrets manager
- Not using remote state — local state files get lost and can't support team collaboration
- Giant monolithic configurations — break infrastructure into focused, composable modules