---
description: Infrastructure as Code—Terraform layout, version constraints, state, modules, drift detection. Declarative; version and test everything.
alwaysApply: false
---

# Infrastructure as Code

Guidelines for maintainable, secure IaC.

## Core Principles

1. **Declarative** - Describe desired state; no manual one-off changes in production.
2. **Idempotent** - Apply twice = same result.
3. **Version Everything** - Terraform and provider versions pinned; modules versioned.
4. **Test** - Validate and plan in CI; test modules (e.g. Terratest) before apply.

## Terraform Layout

- **Root**: main.tf (primary resources), variables.tf, outputs.tf, versions.tf (required_version, required_providers), backend config. Use locals for common tags and computed values.
- **Modules**: One concern per module (e.g. vpc, eks, rds); expose inputs via variables and outputs. Use in environments via module blocks.
- **Environments**: Separate dirs or workspaces (e.g. dev, staging, production); separate state per env; no shared state for prod.

## Version Constraints

```hcl
terraform {
  required_version = ">= 1.5.0, < 2.0.0"
  required_providers {
    aws        = { source = "hashicorp/aws", version = "~> 5.0" }
    kubernetes = { source = "hashicorp/kubernetes", version = "~> 2.23" }
  }
}
```

## Variables and Validation

- **Variables**: Type and description; validation block for enums or formats (e.g. environment in [dev, staging, production], CIDR format).
- **Sensitive**: Mark sensitive variables; never log or output in plaintext.

## State

- **Remote backend**: S3, GCS, or Terraform Cloud; state locking (DynamoDB or equivalent); encryption at rest.
- **No secrets in state** - Use external secret manager and data sources or env vars for sensitive inputs.
- **Isolation**: One state per environment; avoid cross-env data sources that couple state.

## Drift Detection

- **Scheduled plan**: Run terraform plan on a schedule (e.g. cron); alert on diff. Fix via apply or update code.
- **PR gate**: Plan on PR for changed dirs; require no unexpected changes for main.

## Definition of Done (IaC Change)

- [ ] Lint and validate in CI; plan reviewed.
- [ ] Applied in non-prod first; rollback documented.
- [ ] State in remote backend; no secrets in state.
- [ ] Modules tested (e.g. Terratest) where critical.

## Common Pitfalls

- **No backend** - Local state is lost with the machine; always use remote and locking.
- **Large monolith** - Split by lifecycle and ownership; smaller state and blast radius.
- **Drift ignored** - Detect and fix drift; otherwise code and reality diverge.
