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). Consider main 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).

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.
  • 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.