Terraform multi-environment architecture
A Terraform module structure that supports dev, staging and production without duplicated code or state file chaos.
The problem
Copy-pasted Terraform per environment drifts fast — a fix in staging never makes it to production, or vice versa. This lab builds a module-based structure where environments share logic and differ only in explicit, reviewed configuration.
Architecture
- Reusable Terraform modules for networking, compute and data layers
- Thin per-environment root configurations that call shared modules with different variables
- Remote state per environment, with locking and structured naming conventions
- A CI pipeline that plans on every pull request and applies only on merge to main
Technologies
Design decisions
One root module per environment instead of Terraform workspaces
Workspaces share backend configuration in ways that make it easy to apply to the wrong environment by mistake. Separate roots make the blast radius explicit.
Encapsulate provider configuration inside each root, not inside shared modules
Keeps modules portable and testable independent of any one account or region.
Lessons learned
- Module boundaries matter more than DRY-ing every last line — some duplication is more maintainable than false abstraction
- A plan-on-PR pipeline catches most mistakes before they ever reach apply
Working through something similar?
This lab reflects our own reference work, not a client engagement — but the approach transfers directly.
Start a technical conversation