Back to all blog posts

Terraform and OpenTofu Best Practices

Picture of Soren Martius
Sören Martius Chief Product Officer
Photo of Annu Singh
Annu Singh Technical Content Writer
selina nazareth
Selina Nazareth Developer Relations Manager
Reading Time:4 min read

Master Terraform and OpenTofu best practices to improve collaboration, secure sensitive data, and automate infrastructure. Learn how to manage state, structure code, enforce security, and optimize your Terraform workflow for scalable, reliable Infrastructure as Code (IaC).

Terraform and OpenTofu Best Practices Cover

Using Terraform and OpenTofu well goes beyond writing configurations — it’s about building a foundation that lets engineers collaborate smoothly, keeps code easy to review, and safeguards sensitive data. IaC can feel quite intimidating to new practitioners, but a beginner can usually quickly reach a basic understanding of the tool, and the learning curve is flat. However, after an initial learning period, many practitioners face nuances and issues around how to structure their code correctly, how to manage environments, how to automate their IaC and others.

This article explores some of the most important best practices for managing Infrastructure as Code (IaC) with Terraform and OpenTofu, which will help you improve your Terraform skills!

State Management

Store State Remotely with Locking

Using local state is fine for experimenting, but for anything beyond that, switch to a remote shared state like Google Cloud Storage or AWS S3 with DynamoDB for state locking or Google Cloud Storage with locks to ensure a consistent state file. This setup avoids situations where two engineers accidentally overwrite the state. Adopting a single remote backend for your state is one of the key best practices for effective teamwork.

Pro tip: Regularly back up your state file. While remote backends are robust, having snapshots ensures you’re covered in accidental deletions or misconfiguration. Some backends, like AWS S3, come with a built-in backup mechanism.

Split up Large State Files

Large monolithic state files, often called “terralith,” can slow down Terraform operations and increase the risk of conflicts or errors. Splitting these files by resource type, environment, or logical group minimizes the impact of changes (take a look at our article How to structure and size Terraform Stacks to learn more).

  • Example: For a multi-region setup, separate the state files for each region. For instance, have us-east-1.tfstate and eu-west-1.tfstate . This isolation speeds up execution and limits the scope of potential issues.

Code Management and Structure

Organize Code with Modules

  • Modules help encapsulate reusable components like VPCs, IAM policies, or Kubernetes clusters. Version modules and test them independently to ensure reliability. Example: If you have a module for creating EC2 instances, version it (e.g., v1.0.0 ) and test changes in a staging environment before updating production.

Pin Provider and Module Versions

Locking versions avoids surprises from upstream changes. Use version constraints like ~> 2.5 to allow minor updates while preventing breaking changes. Pro tip: Document the rationale for version constraints in your code to make updates easier for future maintainers.

Separate Environments by Workspaces or Folders

  • Use workspaces for smaller setups and folders for larger ones. For instance, have environments/dev , environments/staging , and environments/prod directories.
  • Tip: Use backend-specific naming conventions, like dev.tfstate , to avoid mixing environments accidentally.

Write Idempotent Configurations

  • Idempotency ensures that running terraform apply multiple times produces the same result. Use computed values like count or for_each to handle dynamic resources.
  • Example: Use count = var.enable_monitoring ? 1 : 0 to toggle resources like CloudWatch alarms based on a flag.

Use Data Sources for Dynamic Data

Instead of hardcoding values, use data sources to fetch information dynamically. Example: Fetch the latest AMI using:

data "aws_ami" "latest" {
  most_recent = true
  owners      = ["amazon"]
  filters = [{
    name   = "name"
    values = ["amzn2-ami-hvm-*"]
  }]
}

Security and Access Control

Secure Sensitive Information

Avoid committing sensitive data to your repository. Use tools like AWS Secrets Manager, HashiCorp Vault, or Azure Key Vault to manage secrets securely. Pro tip: Set up CI/CD pipelines to inject secrets dynamically during runtime rather than hardcoding them in configurations.

Automation and Orchestration

Automate Terraform with CI/CD in GitOps

Implement CI/CD pipelines that validate changes (terraform plan ) and apply them only after reviews. Example: Use GitHub Actions with workflows like:

- name: Terraform Plan
  run: terraform plan -out=tfplan

Validate the changes with terraform fmt, validate, and plan before merging them.

Orchestration

Tools like Terramate or Terragrunt make managing large infrastructures more efficient. Example: Use Terramate to create stacks and manage dependencies, ensuring a robust deployment process.

Preview Changes with terraform plan

Always generate a plan and share it for the peer review. Teams that enforce change reviews catch misconfigurations before they affect production. Pro tip: Use automated Slack notifications or comments on pull requests to share plans for visibility.

Monitoring and Drift Management

Enable Logging and Monitoring of Critical Resources

  • Set up logging for resources like AWS CloudTrail or GCP Logging. Use tools like Datadog or Prometheus for monitoring. Example: Monitor Terraform runs with logs sent to centralized systems like CloudWatch Logs or Splunk. This visibility helps debug issues quickly.

Manage and Minimize Infrastructure Drift

  • Drift happens when changes are made outside Terraform. Run a terraform plan on a schedule to detect and fix inconsistencies early. Pro tip: Use pre-configured alerts in CI/CD pipelines to notify teams of drift. For example, integrate AWS Config or Azure Policy to enforce compliance with your configurations.

Conclusion

Good habits in Terraform make it easier for teams to collaborate, handle changes smoothly, and keep everything running as expected, even as your infrastructure grows. Follow these practices to build a strong foundation for reliable and scalable infrastructure. With tools like Terramate, you can take your workflow to the next level—making orchestration effortless and your Terraform experience packed with powerful features.



Ready to supercharge your IaC?

Explore how Terramate can uplift your IaC projects with a free trial or personalized demo.