keepcalculator

06 Numbers and Powers

Terraform Infrastructure as Code Best Practices

Card No. 06·36438 · Updated · Standard formula, shown below

Terraform infrastructure as code works best when teams keep configuration modular, protect and isolate state, review changes before applying them, and detect drift on a regular schedule. These practices make cloud infrastructure more repeatable and auditable while reducing the risk that concurrent work, manual changes, or a mistaken plan disrupts a service.

How Terraform state works

Terraform configuration describes the desired resources; state records Terraform’s understanding of the resources it manages and links configuration addresses to real infrastructure objects. During a plan, Terraform compares configuration, state, and information refreshed from provider APIs to propose changes. State is therefore operational data, not merely a cache: it can contain resource identifiers and sensitive values, depending on the provider and resource.

By default, Terraform stores state locally in a file. That can be adequate for an individual experimenting in a disposable environment, but it is a poor shared workflow for a team. If two people make changes from separate local state copies, their operations can conflict or overwrite one another’s view. A remote backend gives a team a shared location; some backends also support state locking, which prevents simultaneous operations against the same state.

Choose a remote state design

Use a supported remote backend for shared or production infrastructure, and configure access through the cloud platform’s identity and access controls rather than distributing long-lived credentials. Enable locking when the chosen backend supports it. Locking coordinates Terraform operations; it does not prevent a person from changing a resource directly in the cloud console.

Separate state according to operational boundaries, such as environment, application, or team ownership. A development workspace and a production workspace can be convenient when the infrastructure shape is the same and access boundaries are simple. Separate root configurations and state locations are often clearer when environments need different permissions, lifecycles, or safeguards. Terraform workspaces are not, by themselves, a security boundary.

  • Grant state access only to people and automation that need it, and protect state storage with encryption and appropriate retention controls.
  • Keep backend configuration and credentials out of source code. Use the organization’s standard secret and identity mechanisms.
  • Do not edit state files by hand or delete them to “reset” Terraform. Back up state before administrative changes and use Terraform’s state commands for deliberate migrations or repairs.
  • Use a consistent Terraform and provider versioning approach so local runs and automation interpret configuration predictably.

Build modules with clear boundaries

Modules group related resources behind inputs and outputs. A root module is the working directory Terraform runs; it can call reusable child modules for patterns such as a network, service, or database. A useful module has a coherent purpose, a small and understandable interface, and documented assumptions. Avoid creating a module for every resource: excessive indirection can make plans harder to understand than direct configuration.

For example, a network module might accept a region, address range, and subnet definitions, then expose subnet identifiers for application modules. It should not silently create unrelated application services. Keep environment-specific choices—such as the production address range—in the root configuration or a clearly managed input file, rather than hiding them in module internals.

  • Use descriptive input and output names, variable descriptions, and validation rules where they can reject invalid values early.
  • Prefer explicit inputs over hidden assumptions, and expose only outputs that callers genuinely need.
  • Pin module sources to a reviewed version or commit when reproducibility matters; update deliberately and review the resulting plan.
  • Keep provider configuration and version constraints clear. Reusable modules should state compatible provider requirements without unnecessarily taking control of a caller’s provider setup.

Modules do not automatically provide isolation. If two module instances manage distinct resources, they still share the root module’s state unless separate configurations and state boundaries are used.

Review and apply changes safely

A dependable workflow runs formatting and validation checks, creates a plan, reviews it, and applies the approved change through a controlled process. In continuous integration, authenticate with short-lived or federated identity where available, avoid exposing secrets in logs, and restrict who can approve production changes. A plan is a proposal based on the configuration and the state and provider information available at that time; it is not a guarantee that an apply cannot fail or that external conditions will remain unchanged.

  1. Run terraform fmt and terraform validate to catch formatting and configuration issues.
  2. Run a plan in the intended environment and inspect resource additions, changes, and especially deletions.
  3. Share the plan for review, including its environment and relevant configuration changes.
  4. Apply through the same controlled workflow, then check service health and the resulting Terraform state.

Do not treat a successful plan as approval to make every proposed change. Confirm that the selected workspace or root configuration, account, and region are correct. For sensitive resources, verify replacement or deletion behavior carefully; a small configuration edit can cause a resource replacement when the provider cannot update that attribute in place.

Detect and respond to drift

Drift is a difference between what Terraform configuration specifies and what exists in the infrastructure. It can result from console edits, another automation system, provider-side changes, or a change in what the provider reports. Terraform’s plan is the primary way to see proposed reconciliation, but teams should run plans regularly rather than waiting for the next feature release.

Automated drift detection commonly means scheduling a read-and-plan job for each state boundary, then sending plan results to a review channel or ticket system. A nonzero difference should prompt investigation, not an automatic apply in every case. Determine whether the change was authorized, whether configuration should be updated, and whether Terraform should restore the declared setting. For example, if an operator temporarily changes a setting during an incident, record the intended permanent state in code after the incident rather than leaving the console change undocumented.

Where available, a refresh-only plan can help identify and review changes observed in real infrastructure without proposing configuration changes to make the infrastructure match the code. Use it carefully: updating state to record an out-of-band change is not the same as deciding that the change belongs in the desired configuration. Scheduled plans also need valid credentials, provider availability, and a process for handling failures and stale results.

Common problems and trade-offs

State locking reduces collisions, but a lock can remain after an interrupted operation. First verify that no Terraform run is active; force-unlocking without checking can allow competing operations. State separation limits the scope of changes and access, but too many tiny states add operational overhead and make dependencies harder to coordinate. Choose boundaries based on ownership, lifecycle, and access—not simply on the number of resources.

Another common misconception is that Terraform continuously enforces configuration. It does not: Terraform generally acts when a user or automation runs an operation. Cloud-native policy, monitoring, or configuration-management tools may provide additional controls, but they serve different purposes. Terraform plans reveal differences at run time; alerts and cloud audit logs can help identify changes sooner, while policy checks can reject configurations that violate organizational rules.

Frequently Asked Questions

Should Terraform state be committed to Git?
No for ordinary state files. State can contain sensitive information and changes frequently; use a protected remote backend for shared infrastructure. Commit Terraform configuration and reviewed supporting files, but keep credentials and state out of the repository.

Are Terraform workspaces enough to separate production and development?
Not necessarily. Workspaces distinguish state instances, but they do not inherently create separate permissions or security boundaries. Use separate state locations and access controls when environments require meaningful isolation.

How often should automated drift detection run?
There is no universal schedule. Choose a frequency based on infrastructure criticality, change volume, provider limits, and how quickly the team needs to notice unmanaged changes. Ensure someone reviews findings and failed runs.

Should a drift-detection job automatically run Terraform apply?
Usually not by default. An apply can modify or replace real resources. Review the plan and establish whether code or infrastructure is the intended source of truth before reconciling drift.

What should I do if Terraform state is out of sync?
Stop concurrent runs, inspect the backend and the latest plan, and take a protected backup before making state changes. Use documented Terraform state operations or a carefully reviewed import or refresh workflow; do not hand-edit the file.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →