Infrastructure as Code

Infrastructure as code (IaC) means defining servers, networks, databases, DNS records, IAM policies, and every other piece of infrastructure in machine-readable files that live in version control. Tools read those files and create or update real resources to match. Instead of clicking through cloud consoles, you open a pull request, review a plan of exactly what will change, and apply it through automation.

IaC turns infrastructure into something you can review, test, reproduce, and roll back. It's the foundation for consistent environments, disaster recovery (rebuild from code), audit trails (who changed what, when, and why), and platform engineering. It also introduces its own discipline: state management, drift, module design, and safe change workflows.

TL;DR

Quick Example

A pull-request workflow for Terraform/OpenTofu that plans on every PR and applies on merge:

A typical repository layout separating reusable modules from environment roots:

Core Concepts

Declarative vs Imperative

Provisioning vs Configuration

State

Most declarative tools keep state: a record mapping code to real resource IDs and attributes. State enables diffs and dependency tracking but is sensitive (it can contain secrets) and must not be edited concurrently. Store it in a remote backend (S3 with locking, GCS, Azure Blob, HCP Terraform, Pulumi Cloud), encrypt it, and restrict access.

Plan, Apply, and Drift

A plan compares code, state, and reality, then shows creates, updates, and destroys. Apply executes it. Drift occurs when reality changes outside the tool (manual console edits, other automation). Scheduled plans or dedicated drift detection highlight it so you can reconcile.

Modules and Composition

Modules package resources behind inputs and outputs — a "service" module might create a container service, load balancer, DNS record, and alarms. Good modules encode organizational standards (encryption, tagging, logging) so teams get them by default. Version modules and pin versions in callers.

Testing and Policy as Code

Best Practices

Everything Through Pull Requests

Review code and the plan output together. Require approvals for production changes.

Separate State per Environment and Component

Split state by environment and by blast radius (network, data, applications) so a mistake can't destroy everything at once and plans stay fast.

Use Short-Lived CI Credentials

Authenticate pipelines with OIDC to assume narrowly scoped roles; no long-lived cloud keys in CI secrets.

Keep Secrets Out of Code

Reference secrets from a secret manager rather than hard-coding them, and treat state as sensitive. See Secrets Management.

Protect Stateful Resources

Use deletion protection, prevent_destroy lifecycle rules, and backups for databases and buckets.

Tag Everything

Enforce owner, environment, and cost-center tags in modules and policy so resources are attributable. See Cloud Costs.

Common Mistakes

Applying From Laptops

Local applies with personal credentials bypass review and create untraceable changes. Apply from CI.

One Giant State File

Every plan touches everything, takes minutes, and a single error blocks all teams.

Console "Quick Fixes"

Manual changes drift from code and get reverted or cause conflicts on the next apply.

Ignoring Destroy and Replace in Plans

Renaming a resource or changing an immutable property can replace a production database. Read plans carefully and use moved blocks or aliases when refactoring.

Copy-Pasted Environments

Duplicated code per environment drifts apart. Use modules with environment-specific inputs.

Comparison

FAQ

What is infrastructure as code?

Managing infrastructure through versioned code files that tools apply automatically, instead of manual console changes — making infrastructure reviewable, repeatable, and auditable.

What's the difference between declarative and imperative IaC?

Declarative IaC describes the desired end state and lets the tool determine the changes. Imperative IaC lists steps to execute. Declarative tools are easier to preview and make idempotent.

Why does Terraform need a state file?

State maps resources in code to real-world resources and stores their attributes, so the tool can compute accurate diffs, track dependencies, and manage resources it created.

How do I handle drift?

Detect it with scheduled plans or drift detection features, then either update the code to accept the change or re-apply to revert it. Prevent it by restricting manual write access.

Should I use Terraform or Pulumi?

Terraform/OpenTofu has the largest ecosystem and a simple declarative language. Pulumi suits teams that want general-purpose languages, stronger abstractions, and unit testing. Both work well.

Related Topics

References