
for_each, early variable evaluation, and the -exclude flag.tofu init -upgrade, run tofu plan. If the plan reports no changes, you're done. Our What is OpenTofu? guide walks the full sequence.Reviewed for accuracy by Ryan Fee on May 12, 2026.
The Terraform and OpenTofu split is no longer just a licensing debate. In 2024 the question was "is OpenTofu safe to try?" In 2026 the better question is "which roadmap do we want to depend on?" The answer turns less on language syntax and more on governance, state handling, orchestration patterns, and how much HCP Terraform a team already runs.
Disclosure. Scalr supports both Terraform and OpenTofu and was a founding contributor to OpenTofu. We have a commercial interest in customers using platforms that support both engines. The goal of this article is to separate what is actually different from what is just branding.
| Dimension | OpenTofu | Terraform |
|---|---|---|
| License | MPL 2.0 | BSL 1.1 since 1.6 |
| OSI-approved open source | Yes | No |
| Governance | Linux Foundation / CNCF Technical Steering Committee | HashiCorp / IBM |
| Binary | tofu |
terraform |
| State compatibility | Strong compatibility with Terraform 1.5-era state; later states should be tested | Native |
| Default registry | registry.opentofu.org |
registry.terraform.io |
| State encryption in CLI | Built-in since v1.7 | No equivalent in open CLI |
Provider for_each |
Yes, v1.9+ | No |
| Early variable evaluation | Yes, including backend configuration | Partial / different scope |
-exclude flag |
Yes, v1.9+ | No |
| Loopable import blocks | Yes, v1.8+ | No equivalent |
| OCI registry support | Yes, for providers and modules | No equivalent general-purpose open CLI feature |
| Native testing | tofu test |
terraform test |
| Terraform Stacks | No production-equivalent feature yet | HCP Terraform feature |
For roughly nine years, Terraform was open source in the way most engineers mean it. From its first release in 2014 through July 2023, every line shipped under the Mozilla Public License v2.0. You could read it, run it, modify it, and build a product on top of it without asking permission.
That ended on August 10, 2023. In one announcement, HashiCorp re-licensed Terraform, Vault, Consul, Nomad, Boundary, Packer, and Waypoint under the Business Source License 1.1, which is not an OSI-approved open source license. The code stayed publicly visible, but the new license added a restriction: you could no longer use it to build a product that HashiCorp considered competitive with its own offerings.
Within weeks, a coalition that included Gruntwork, Spacelift, Harness, env0, and Scalr published the OpenTF manifesto and announced a fork from the last MPL release. In mid-September, the project moved to the Linux Foundation, renamed itself OpenTofu, and gave the CLI a new binary name (tofu). We covered that move in Finding a home for OpenTofu.
OpenTofu v1.6 followed in January 2024 with full compatibility back to Terraform 1.5. Since then:
for_each, and the -exclude flag.moved and removed blocks, external key providers).enabled meta-argument, while continuing to evolve independently from Terraform's roadmap.At this point, treating OpenTofu as just a renamed Terraform 1.5 fork is outdated. It is a separately governed project with three years of independent decisions behind it.
For an engineer typing tofu apply against their AWS account, the difference between MPL 2.0 and BSL 1.1 is invisible. Both binaries call the same APIs. The license question only surfaces when somebody asks who else is allowed to do that.
MPL 2.0 is what most engineers mean when they say "open source." Use it for anything. Sell products built on it. Modify it, as long as the modifications to MPL files go back under MPL. There is no clause that asks what business you're in.
BSL 1.1 reads differently. You can run it, you can read it, and you can extend it for your own use. What the additional use grant restricts is using Terraform to provide a service that HashiCorp considers competitive with its own offerings. Each released version eventually flips to MPL, but only four years after that version's release date. The practical implication for vendors that offer managed Terraform services is that they need to take a position on whether their service falls inside or outside the grant; some have continued, some have switched their managed offering to OpenTofu, and a few have asked HashiCorp directly.
Most internal platform teams will not feel this difference in daily usage. If you are running Terraform on your own pipelines against your own cloud accounts, the BSL usually has no effect on what you do day to day. It starts to matter when legal or procurement asks whether the IaC tooling is open source, particularly in public sector environments where that question is answered against the OSI list. It matters more if your product or service involves running Terraform on behalf of other customers.
OpenTofu and Terraform overlap on most of their feature surface. Resources, data sources, providers, modules, variables, locals, outputs, tfvars files, workspaces, and backends behave the same way in both tools, which is the main reason migration is cheap. Most teams will not notice the fork during a normal plan or apply. They notice it in these areas.
State files are the most sensitive thing a Terraform user produces. Database credentials, API tokens, private endpoints, the entire shape of your infrastructure: all of it ends up serialized as plaintext JSON. Remote backends like S3 will encrypt the file at rest, but that protects the bucket, not the workflow. Anyone who can pull state can still read it.
OpenTofu v1.7 closed that gap by adding encryption to the CLI itself. The block looks like this:
terraform {
encryption {
key_provider "aws_kms" "ops" {
kms_key_id = "alias/opentofu-state"
region = "us-east-1"
}
method "aes_gcm" "default" {
keys = key_provider.aws_kms.ops
}
state {
method = method.aes_gcm.default
}
plan {
method = method.aes_gcm.default
}
}
}Key providers include PBKDF2 passphrases for solo work, AWS KMS or GCP KMS for cloud-native setups, and OpenBao for self-hosted environments. Terraform's open CLI does not provide an equivalent configuration-level state encryption feature. HCP Terraform offers platform-level state storage protections, but those are managed by HashiCorp's service and are not equivalent to portable, CLI-managed encryption that travels with your own backend.
for_eachDeploying the same module across multiple AWS regions used to require a copy-pasted provider block per region. OpenTofu 1.9 made provider configurations iterable. The alias is static, and each.value selects the region from the iteration:
variable "regions" {
type = set(string)
default = ["us-east-1", "eu-west-1", "ap-southeast-2"]
}
provider "aws" {
alias = "by_region"
for_each = var.regions
region = each.value
}
module "regional" {
source = "./regional"
for_each = var.regions
providers = {
aws = aws.by_region[each.key]
}
}The iterated provider is consumed by passing aws.by_region[each.key] through the module's providers block. In Terraform, this still requires a hand-written provider block per region.
For most of Terraform's history, the top-level terraform { backend { … } } block did not evaluate variables, locals, or data sources. This restriction is part of why teams reach for Terragrunt, which uses a templating layer above Terraform to inject backend configuration per environment. OpenTofu 1.8 lifted the restriction directly:
locals {
env = var.environment
}
terraform {
backend "s3" {
bucket = "tfstate-${local.env}"
key = "${local.env}/terraform.tfstate"
}
}This removes a common reason for wrapper scripts and templating in multi-environment setups. The full pattern is covered in dynamic backend blocks with OpenTofu. Terragrunt still has reasons to exist on top of OpenTofu (dependency graphs, run-all, output sharing across stacks), but per-environment backend variation is no longer one of them.
Terraform has added some flexibility in newer releases (for example, variables and locals in module source and version attributes), but OpenTofu's early-evaluation support remains broader in workflow areas such as backend configuration.
-targetterraform apply -target=foo has existed since the early Terraform releases. It is useful when you want to apply a single resource, but it is the wrong tool when you want to apply everything except one or two resources. OpenTofu 1.9 added the matching flag:
# Apply everything except the production database
tofu apply -exclude 'aws_db_instance.prod'
# Two resources at once
tofu apply \
-exclude 'aws_db_instance.prod' \
-exclude 'aws_rds_cluster.analytics'Phased rollouts, blast-radius control, "leave that resource alone while it's being manually fixed" workflows all get simpler with this flag.
Stacks is the one item on this list that Terraform has and OpenTofu does not. HashiCorp's Stacks lets you orchestrate many configurations under a shared lifecycle. Stacks are defined in configuration files and have CLI integration, but the managed lifecycle that makes Stacks useful is an HCP Terraform feature rather than a standalone open-CLI workflow. If you need that orchestration pattern on the OpenTofu side today, the options are Terragrunt's run-all, a TACoS platform that orchestrates multiple workspaces (Scalr, Spacelift, env0), or waiting on the OpenTofu community's in-progress Stacks RFC. None of these is a feature-for-feature replacement for Stacks as HashiCorp implements it.
In most practical cases, both engines use the same provider artifacts. The default registry host differs between the two, and explicit source addresses or lock files may need review during a migration. The widely used providers (AWS, Azure, GCP, Kubernetes, and the other major ones) are distributed through both registries. For less common or newly published providers, teams should verify availability and source addresses during migration.
| Source | OpenTofu default | Terraform default |
|---|---|---|
registry.opentofu.org |
Yes | Available if explicitly pinned |
registry.terraform.io |
Available if explicitly pinned | Yes |
A standard required_providers block:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}works in both engines. OpenTofu resolves hashicorp/aws to its own registry; Terraform resolves it to HashiCorp's. If your existing configuration explicitly pins source = "registry.terraform.io/hashicorp/aws", OpenTofu honors that and pulls from HashiCorp's registry instead of its own. During a migration, it is worth reviewing the required_providers blocks and the lock file (.terraform.lock.hcl) to confirm the source addresses and checksums match what your team intends.
For routine init, plan, and apply workflows, the commands are nearly identical:
| Operation | OpenTofu | Terraform |
|---|---|---|
| Initialize | tofu init |
terraform init |
| Plan | tofu plan |
terraform plan |
| Apply | tofu apply |
terraform apply |
| Destroy | tofu destroy |
terraform destroy |
| Import (CLI) | tofu import |
terraform import |
| Import (block) | v1.6+, looped in v1.8+ | v1.5+ |
| State surgery | tofu state ... |
terraform state ... |
| Format | tofu fmt |
terraform fmt |
| Validate | tofu validate |
terraform validate |
| Console | tofu console |
terraform console |
| Native tests | tofu test |
terraform test |
Most Terraform 1.5-era configurations run on OpenTofu without modification. The compatibility direction that doesn't hold is forward: configurations that use a Terraform 1.6+ exclusive feature (mostly HCP-only blocks) won't run on OpenTofu, and configurations that use OpenTofu-specific features (state encryption blocks, provider for_each, the -exclude flag) won't run on Terraform. For a more granular language-level diff, the OpenTofu Language Guide has the full surface.
Governance sounds abstract until a roadmap decision affects you. Over a multi-year horizon it tends to drive more of the practical differences than any single feature.
OpenTofu's roadmap is set by a Technical Steering Committee under the Linux Foundation, with the project also sitting inside the CNCF. The committee is multi-vendor by design: no single company has the votes to override the others, and feature direction is decided through public RFCs that anybody can read. There are weekly community calls. The minutes are on GitHub. When a contentious change gets argued about, the argument is in the open.
Terraform's roadmap is set inside HashiCorp, which is now an IBM subsidiary. The release notes are public, the issue tracker is public, but the strategic calls (the BSL relicense, the decision to make Stacks HCP-only, anything about the future of the Terraform Registry itself) are made internally. Community input flows through GitHub issues and HashiCorp's product management, and what gets prioritized is what aligns with HashiCorp's (now IBM's) commercial strategy.
Both models have trade-offs. Foundation governance can be slower to reach decisions, and it depends on the contributors who actively participate in meetings and RFCs. Vendor governance is faster, but concentrates decision-making inside one company whose commercial interests may not match yours. Which trade-off matters more to your team usually depends on whether you trust the vendor's long-term direction.
There are still cases where staying on Terraform makes sense:
For teams that are not deeply committed to HCP Terraform-specific workflows, OpenTofu is increasingly the default recommendation. The reason is not that Terraform stopped working. It is that OpenTofu now has enough independent feature momentum that the license and governance advantages no longer come with much operational penalty:
for_each, early variable evaluation, and the -exclude flag have been frequently requested by Terraform users and shipped in OpenTofu first.OpenTofu is not a zero-risk switch. The biggest costs are not in the common Terraform language features; they are in the edge cases:
terraform binary name, hardcoded paths, or specific environment variables.registry.terraform.io.None of these is usually a blocker on its own. Together they are why a migration that looked like a five-minute binary swap can take an afternoon, and why a phased rollout per workspace is the standard recommendation rather than a single-day org-wide cutover.
For most workspaces, migrating from Terraform to OpenTofu is mechanical:
terraform plan and confirm there are no pending changes.tofu binary alongside terraform. The two binaries do not conflict on PATH.tofu init -upgrade to rewrite the lock file against the OpenTofu registry.tofu plan. This is where you find out whether anything in the configuration depends on a Terraform feature that OpenTofu does not support.tofu apply. The next state write replaces the terraform_version marker with OpenTofu's version. The resource entries in state are unchanged.If you are on Terraform 1.5.x, migration is essentially a no-op. If you are on Terraform 1.6 or later, audit your configuration for HCP-exclusive features (Stacks, no-code modules, certain remote backend extensions) before switching; for most workspaces this audit takes minutes. The What is OpenTofu? guide covers the playbook in more detail, and debugging OpenTofu apply failures covers the issues that occasionally arise after migration (most commonly authentication or stale state locks).
In practice, performance is comparable. Both engines build the same resource graph, parallelize at the same depth, and bottleneck on the same external provider APIs. For typical workloads, variance in plan and apply times is dominated by cloud API latency rather than by anything the engine itself does.
Stability is also comparable. OpenTofu's first releases after the fork had the rough edges that any new project has, but the release cadence from v1.7 onward has been steady. Regressions are caught in CI, and OpenTofu inherits the existing Terraform test suite as a baseline.
Most third-party tooling works with both engines:
terraform and tofu.tflint, tfsec, checkov, tfupdate, and tflocal all run against both.terraform-ls Language Server treats .tf and .tofu files interchangeably, and the VS Code Terraform extension works against either engine.Older scripts and CI configurations that hardcode the terraform binary name or registry.terraform.io URLs do need to be updated. Most actively maintained tooling has added OpenTofu support since 2024, so this tends to be a one-time audit rather than ongoing friction.
A fork. It started from Terraform 1.5.x's codebase and inherits the full pre-fork git history. From v1.6 onward, the two projects develop independently.
Yes, and many teams do during migration. The binaries don't conflict on PATH, so install both and pick per project. Scalr (and most other TACoS) lets you set the engine per workspace, which is how most teams roll out OpenTofu gradually.
State produced by Terraform 1.5.x generally works in OpenTofu without conversion, and many later Terraform states also work as long as the configuration does not depend on Terraform-only features. Always run tofu plan first to confirm OpenTofu reads the state cleanly before applying. On the first tofu apply, the terraform_version marker in state is rewritten to OpenTofu's version; the resource entries are not modified.
No. Same binaries, same release pipelines. The only difference is which registry your required_providers resolves against by default, and you can pin to either explicitly if it matters.
The BSL's additional use grant does not name OpenTofu specifically. More importantly, OpenTofu was forked from a pre-BSL MPL-licensed release, so the BSL does not apply to OpenTofu's codebase. The Linux Foundation and OpenTofu's legal counsel reviewed the licensing position before the fork was published.
There has been no public announcement to that effect as of May 2026. IBM has historically maintained open-source licenses on its acquisitions (Red Hat being the most prominent example), but the BSL on Terraform remains in place.
OpenTofu is the lower-risk choice for most new IaC adoptions. It provides an OSI-approved license, multi-vendor governance, full provider compatibility, and the recent CLI features described above. Teams that already pay for HCP Terraform and use Stacks heavily should evaluate the Stacks dependency before switching.
The operational takeaway from the comparison above is not that every team must standardize on one engine immediately. The safer pattern is to support both, migrate workspace by workspace, and keep the execution platform from becoming the bottleneck.
Scalr was a founding contributor to OpenTofu, and supports both engines in the same account. From a Scalr account you can:
For teams in the middle of evaluating OpenTofu while still running existing Terraform workspaces, a runtime that supports both engines removes the need to commit to one engine across all workspaces at once.
OpenTofu and Terraform are no longer interchangeable products with different names. They differ on licensing (MPL 2.0 vs BSL 1.1), on governance (Linux Foundation vs HashiCorp/IBM), and on a set of CLI features that have shipped in OpenTofu but not in Terraform's open-source CLI. For most teams, migration is mechanical, and OpenTofu's independent feature momentum has narrowed the operational gap between the two. Cases where staying on Terraform makes sense in 2026 include HCP Stacks dependencies, IBM Cloud Pak environments, and procurement structures that specifically require HashiCorp as a vendor.
For a deeper reference on OpenTofu itself, see What is OpenTofu?. For pipeline patterns that apply to both engines, see our CI/CD guide for Terraform and OpenTofu.
