Updated: 2026-07-07

Terraform 1.6, released in October 2023, was the first version shipped under the new Business Source Licence. That change triggered, within days, the announcement of OpenTofu as a community fork backed by the Linux Foundation, branching from Terraform 1.5. Over a year later, with Terraform 1.9 in production and OpenTofu 1.8 stable, it is worth a calm review of what HashiCorp has been delivering, what the fork offers, and which additions actually matter in the daily life of a team writing declarative infrastructure.

Key takeaways

  • Declarative import blocks in 1.6 are the most transformative change: importing existing infrastructure goes from an afternoon of CLI commands to a reviewable pull request.

  • The native testing framework validates module logic in HCL without learning Go or leaving the existing stack.

  • Ephemeral values in 1.9 prevent dynamic secrets from being persisted in the state file.

  • OpenTofu is drop-in compatible, with interchangeable state, and adds native state-file encryption.

  • The Terraform vs OpenTofu decision comes down to three questions: HashiCorp contract?, need stacks or native encryption?, what does internal policy say about BSL?

What 1.6 actually changed

The headline feature of Terraform 1.6 was declarative import blocks. Until then, importing an existing resource into state meant running terraform import from the CLI, remembering the exact provider ID, and then writing the corresponding resource block by hand. With declarative import, the plan shows what is going to be imported before any apply, the code is versioned in Git, and dozens of resources can be imported in a single review cycle. For teams inheriting infrastructure built in the console or through another tool, this is the difference between an afternoon of CLI commands and a reviewable pull request.

The other structural novelty in 1.6 was the native testing framework. Until that point, testing Terraform modules meant Terratest (Go), kitchen-terraform, or other external options. The native framework introduces .tftest.hcl files that describe run blocks with commands (plan or apply), test-specific variables, and assertions against outputs.

run "validate_vpc_cidr" {
  command = plan
  variables {
    cidr_block = "10.0.0.0/16"
  }
  assert {
    condition     = module.vpc.cidr_block == "10.0.0.0/16"
    error_message = "VPC CIDR does not match the supplied parameter"
  }
}

Since 1.7 these tests run in parallel, which makes a broad suite viable in CI. It does not replace Terratest for genuine integration tests against a cloud provider, but it covers a significant gap: validating module logic without leaving HCL or learning Go.

The useful bits of 1.7 and 1.8

Terraform 1.7 added the removed block, the conceptual counterpart of moved. It removes a resource from state declaratively, without destroying it, by writing a block that states the retired address. Before this existed, the only option was terraform state rm, an imperative command that leaves no trace in the codebase. Now the operation appears in the plan and is audited in the repository, exactly where infrastructure changes should live.

Version 1.8 brought provider-defined functions. Providers can export custom functions accessible via the syntax provider::<name>::function(...). The AWS provider, for example, publishes functions for parsing ARNs without brittle regular expressions.

Ephemeral values and module validation in 1.9

The most interesting addition in Terraform 1.9 is ephemeral values: values that materialise during plan or apply but are never written to the state file. The obvious use case is secrets: dynamically generated passwords, tokens pulled from Vault or AWS Secrets Manager, temporary credentials. Until now, even with sensitive = true, these values ended up encrypted inside the state, with the risk that implies if the backend is ever compromised. With ephemeral, the value is used during the cycle and then gone. It does not solve every secret-management problem in IaC, but it shrinks the exposure surface in a way teams have wanted for years. This approach to ephemeral secrets connects with the supply-chain principles examined in SLSA v1.0.

1.9 also tightened module input validation. Variables can refer to other variables in the same module inside validation rules, which allows cross-rule checks along the lines of "if parameter A is prod, parameter B must be set".

Stacks: the feature that can shift patterns

As of late 2024, stacks is still in private preview on HCP Terraform. The promise is ambitious: a single module deployed across multiple environments with explicit cross-stack dependencies, coordinated orchestration, and a state model that understands the relationship between instances.

OpenTofu: the fork is real

By late 2024, OpenTofu has a clear track record:

  • Drop-in compatible for most configurations; state is interchangeable.

  • Providers work identically.

  • Adds native state file encryption (absent in Terraform).

  • Remains under MPL 2.0, guaranteeing free software permanently.

  • Lacks stacks and ephemeral values in its current implementation.

What to watch and what to ignore

Of all the additions, the ones that genuinely change a team’s daily work are:

  • Import blocks: they transform how existing infrastructure is adopted.

  • Testing framework: makes TDD viable for HCL modules.

  • removed block: closes the declarative lifecycle of state management.

  • Ephemeral values: shrink the secret-exposure surface.

Everything else, including HCP Terraform’s rebranding and the minor additions in individual providers, barely moves the needle for a team with a stable existing workflow. Stacks deserves attention because it may consolidate existing tooling, but it is still too early to base architectural decisions on it.

Conclusion

The Terraform vs OpenTofu choice boils down to three questions: do you have a contract with HashiCorp or HCP? do you need stacks or native state encryption? what does internal policy say about BSL? Those answers make the decision write itself, and both tools are going to stay usable for a long time.