Terraform Monorepo vs Polyrepo Cheatsheet
Quick cheat-sheet comparing Terraform monorepo vs polyrepo: pros, cons, workflows, scaling, and team tips to choose the right repo strategy.
This cheatsheet provides a quick reference to the core principles, strategies, and best practices for structuring your Infrastructure as Code (IaC) with Terraform and OpenTofu, derived from the four-part "Platform Engineer's Guide."
I. Foundational Principles
- Why Structure Matters: Critical for maintainability, scalability, collaboration, onboarding, troubleshooting, and compliance. A deliberate structure is non-negotiable.
- Standard Files:
main.tf
: Primary resource definitions.variables.tf
: Input variable declarations (types, descriptions, defaults).outputs.tf
: Output value definitions.versions.tf
: Terraform/OpenTofu and provider version constraints.terraform.tfvars
(or*.auto.tfvars
): Variable value assignments (often per environment).
- Naming Conventions:
- General: Use underscores (
_
) for separation. Be descriptive and consistent. - Resources: Singular names (e.g.,
aws_instance.web_server
). Considermain
for primary resources in a module. - Variables: Descriptive. Include units for numerics (e.g.,
ram_size_gb
). Use positive booleans (e.g.,enable_monitoring
). - Outputs: Descriptive of the value provided.
- Files: Group related resources logically (e.g.,
network.tf
,compute.tf
).
- General: Use underscores (
II. Effective Modularity
- Core Benefits of Modules: Reusability, abstraction, complexity management, consistency, organization.
- Module Design Principles:
- Clear Focus: Single, well-defined responsibility.
- Avoid Thin Wrappers: Unless adding significant value (e.g., enforcing standards).
- Logical Grouping: Encapsulate resources that work together.
- Parameterize Sparingly: Expose only necessary variables; use sensible defaults.
- Clear Outputs: Define necessary outputs for downstream consumption.
- Manageable Size: Not too big, not too small.
- Documentation:
README.md
with purpose, inputs, outputs, examples. - Versioning: Use semantic versioning for shared modules.
III. Repository & Code Organization
- Monorepo vs. Polyrepo:
- Monorepo: (All IaC in one repo)
- Pros: Unified visibility, atomic cross-component changes, easier internal dependency management.
- Cons: CI bottlenecks, access control complexity, large repo size.
- Polyrepo: (IaC split into multiple repos, e.g., per module/service/env)
- Pros: Clear ownership, smaller repos, independent lifecycles, granular access.
- Cons: Discovery challenges, complex cross-repo dependency management, potential code duplication.
- Choice Factors: Team size, project complexity, organizational culture, CI/CD capabilities.
- Monorepo: (All IaC in one repo)
- Folder Structure Tips:
- Consistency is Key: Choose a pattern (e.g., environment-first, component-first) and stick to it.
- Local Modules: Often in a top-level
modules/
directory. - Environment Configs: Use
.tfvars
files (e.g.,dev.tfvars
,prod.tfvars
) or separate directories per environment.
IV. Environment & State Management
- Environment Parity: Aim for non-production environments to closely mirror production.
- Use the same versioned modules across environments.
- Drive differences via configuration (variables), not forked code.
- State Management Best Practices:
- Separate State Files: Crucial. One per environment/component/region to minimize blast radius. Avoid monolithic state.
- Remote Backends: Always use (e.g., AWS S3, Azure Blob, GCS). Enables collaboration, CI/CD, durability.
- State Locking: Essential. Prevents concurrent modifications and state corruption.
- Logical Backend Keys/Paths: Structure paths consistently for easy location (e.g.,
<project>/<env>/<region>/<component>/terraform.tfstate
). - Enable Versioning: On your remote backend storage (e.g., S3 bucket versioning) for rollback capability.
- Secure State: Encrypt state at rest. Strictly control access (IAM).
V. Scaling & Advanced Patterns
- Adapting to Growth:
- Treat IaC structure as living code; refactor iteratively.
- Decompose/compose modules as needed.
- Manage shared services with clear interfaces and versioning.
- Balance autonomy with governance (Policy as Code, Platform as a Product).
- Dependency Management:
- Terraform infers most (implicit).
depends_on
: Use sparingly for explicit ordering.terraform_remote_state
: For loosely coupled cross-stack dependencies (reading outputs).
- Terragrunt Highlights (Orchestration Tool):
- DRY Configurations: Inherit common settings (backend, providers, variables).
- Automated Backend Config: Simplifies remote state setup.
- Dependency Orchestration: Manage dependencies between separate Terraform configurations/stacks.
run-all
Commands: Execute Terraform across multiple modules in dependency order.
VI. Continuous Improvement
- Key Metrics for Success: Lead time for changes, deployment frequency, change failure rate, MTTR, code reusability, onboarding time.
- Feedback Loops:
- Regular code reviews (focus on structure too).
- Team retrospectives on IaC practices.
- Automated testing:
terraform fmt
,validate
, static analysis (tfsec, Checkov), policy checks (OPA). - Monitor CI/CD pipeline performance.
- Stay updated with IaC tooling and best practices.
This cheatsheet should serve as a valuable quick-reference as you structure and scale your Terraform and OpenTofu projects.