Terragrunt vs OpenTofu vs Terraform Stacks: Infrastructure-as-Code at Scale (2026)
Most teams that ask “terragrunt vs opentofu” are asking the wrong question, and the confusion costs them a quarter of migration work. Terragrunt is an orchestrator that wraps an engine. OpenTofu is an engine, a fork of Terraform that is also a drop-in runtime for Terragrunt. Terraform Stacks is an orchestration layer built into HashiCorp’s commercial platform. Comparing them head to head only makes sense once you separate the three layers that every large infrastructure-as-code (IaC) estate needs: the engine that plans and applies, the orchestration layer that decides what runs in which order across hundreds of state files, and the state backend that stores the result.
This matters now because 2026 changed all three layers at once. Terragrunt shipped 1.0 with a stability promise in March, Terraform Stacks has been generally available since September 2025, and OpenTofu has shipped three releases since late 2025. You can no longer pick the “default” and drift.
You will leave with a layered mental model, a worked blast-radius calculation, the real differences in secrets and state handling, a decision matrix, and the failure modes each option hides.
What this covers: the layering model, how each tool scales a monorepo, state and secrets handling, a decision matrix, gotchas, and a checklist.
Context and Background
Terraform became the lingua franca of cloud provisioning because a single declarative language could describe resources across vendors. The cost showed up at scale. A single root module with one state file works for a dozen resources. At ten thousand resources, terraform plan takes minutes, every apply locks the whole state, and one bad merge can touch production and staging together. The industry answer was to split state into many small root modules, one per environment, region and component. That solved blast radius and created a new problem: someone has to run those hundreds of root modules in dependency order, pass outputs between them, and keep backend configuration from being copy-pasted into every directory.
Three answers emerged. Gruntwork’s Terragrunt, started nearly a decade ago, generates backend and provider configuration and runs many root modules as a graph. HashiCorp built Terraform Stacks, which models a multi-component, multi-environment deployment as a first-class object in HCP Terraform. And after HashiCorp moved Terraform to the Business Source License in 2023, the community forked it as OpenTofu under the Linux Foundation, later hosted by the CNCF. IBM’s acquisition of HashiCorp, widely reported in 2025 and 2026, added a vendor-strategy variable that many platform teams now weigh explicitly. For the licensing and ecosystem background, see our earlier Terraform vs Pulumi vs Crossplane comparison.
Version status as of this writing, taken from vendor pages checked on 2 November 2026:
| Tool | Current milestone | Source |
|---|---|---|
| Terragrunt | 1.0 announced 30 March 2026 | Gruntwork |
| OpenTofu | 1.11.0 on 9 Dec 2025, 1.12.0 on 14 May 2026, 1.13.0 on 29 Sep 2026 | OpenTofu blog |
| Terraform Stacks | GA announced 25 Sep 2025 for new HCP Terraform plans | HashiCorp |
| Terraform CLI | 1.15 released 29 Apr 2026; endoflife.date also lists later lines | endoflife.date |
I could not verify every feature of the newest OpenTofu 1.13 line this run, so statements about OpenTofu below are anchored to the 1.11 and 1.12 releases and the state-encryption documentation.
The platform context also matters. If your organization is building an internal developer platform, IaC orchestration is one layer of a larger golden-path story; our piece on platform engineering and internal developer platform golden paths covers how Crossplane and IaC fit together.
The Layered Model: Engine, Orchestrator, State
Before comparing products, fix the vocabulary. An IaC estate has four layers, shown below, and each tool in this article occupies a different subset of them.
Direct answer: Terragrunt is an orchestration wrapper that runs OpenTofu or Terraform across many units. OpenTofu is an open-source engine and a fork of Terraform. Terraform Stacks is HashiCorp’s built-in orchestration for multi-component, multi-environment deployments in HCP Terraform. They are not substitutes at the same layer, so the real choices are engine plus orchestrator.

Figure 1: The four layers of an IaC monorepo. Terragrunt and Stacks compete at layer 2; OpenTofu and Terraform compete at layer 3.
The diagram reads top to bottom. Module code at layer 1 is portable HCL and is largely identical between OpenTofu and Terraform for versions that share a feature set. Layer 2 is where the products diverge: Terragrunt reads terragrunt.hcl files and shells out to a binary, while Stacks reads .tfcomponent.hcl and .tfdeploy.hcl files and runs inside HCP Terraform. Layer 3 is the engine binary. Layer 4 is the state backend, where the real operational risk lives.
Layer 2 is where scale is won or lost
A single engine invocation understands one root module and one state. It has no concept of “apply the network, then the database, then the application, passing outputs forward.” Without an orchestrator, teams write Makefiles, shell loops or CI matrices. Those work until the dependency graph has a diamond in it, at which point ordering bugs appear and parallelism is either absent or unsafe. An orchestrator owns three things: the dependency DAG (directed acyclic graph), configuration inheritance such as backend and provider blocks, and selection of which subset to run.
The engine is the smaller decision than it looks
OpenTofu and Terraform started from the same code base and share HCL syntax. They have diverged on features. OpenTofu 1.11 added ephemeral values and resources, write-only attributes and an enabled lifecycle meta-argument, per the OpenTofu 1.11 release post. OpenTofu 1.12 added dynamic prevent_destroy, import by resource identity and provider-installation improvements, per the blog index. Terraform has its own ephemeral and write-only features and, importantly, Stacks, which exist only on the HashiCorp side. For ordinary modules, the engine swap is usually a binary change plus a lock-file refresh. For Stacks, it is a platform change.
The state backend is the shared dependency
Whatever sits at layers 2 and 3, state lives in one place per unit: an S3 bucket with locking, a GCS bucket, Azure Blob storage, or HCP Terraform. The orchestrator decides how many state files exist and how they are named. That count is the single most important sizing number in the estate, and the next section shows how to compute it.
How Each Option Scales a Monorepo
Terragrunt: units, stacks and a DAG runner
Terragrunt’s unit of work is the unit: a directory containing a terragrunt.hcl that points at a module source, supplies inputs and declares dependencies. A unit has exactly one state file. A stack is a collection of units that you generate and run together. Terragrunt 1.0, announced on 30 March 2026, calls stacks the recommended way to define higher-level infrastructure patterns and keeps units as the independently deployable building blocks, per the 1.0 announcement.
A minimal unit looks like this (illustrative; verify attribute names against current docs before use, untested here):
# live/prod/eu-west-1/database/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "git::https://example.com/modules.git//rds?ref=v4.2.0"
}
dependency "vpc" {
config_path = "../vpc"
}
inputs = {
vpc_id = dependency.vpc.outputs.vpc_id
subnet_ids = dependency.vpc.outputs.private_subnet_ids
}
The root.hcl file holds the remote_state block with a templated key such as ${path_relative_to_include()}/tofu.tfstate, so every unit gets a unique state key with no copy-paste. That single mechanism is why Terragrunt exists: backend boilerplate is generated, not written.
The 1.0 release stabilized a set of surfaces: CLI flags, the serialized output of find and Run Reports, HCL configuration, and the stdout and stderr enrichment of the underlying engine. It renamed run-all to run, dropped the --terragrunt- flag prefix, and added exec, backend bootstrap, find and list commands. A single --filter flag replaced seven legacy flags and can target units by path, configuration attributes, the dependency graph and Git diffs. Gruntwork also states that a revamped Runner Pool improves concurrency while respecting the DAG, and that a shared provider cache is configured automatically when OpenTofu is 1.10 or later.
The dependency DAG in practice

Figure 2: A unit DAG. A Git-diff filter selects only the changed unit and its dependents, so a small change does not trigger a full-estate plan.
Terragrunt computes the graph from dependency and dependencies blocks. Units with no unmet dependencies run in parallel up to the configured concurrency. The filter flag is what makes monorepo CI affordable: instead of planning every unit on every pull request, CI asks for units whose files changed in the diff plus anything downstream. The exact filter expression syntax is documented by Gruntwork; I did not test expressions in this run, so treat the concept, not the syntax, as the takeaway.
Terraform Stacks: components and deployments
Stacks takes a different shape. Instead of many independent root modules wired by an external tool, a Stack is one configuration made of components (each wrapping a module) that is instantiated as multiple deployments, for example dev, staging and prod or one per region. Stacks became generally available on 25 September 2025 for new HCP Terraform plans, priced by resources under management, with API backward-compatibility guarantees and a unified CLI, per HashiCorp’s HashiConf 2025 post.
The GA release was not a pure continuation of the beta. According to the beta-to-GA migration page:
<NAME>.tfstack.hclis no longer supported; component configuration uses<NAME>.tfcomponent.hcl.- The
auto_approve,orchestrateandreplanblocks are deprecated. Auto-approval moves intodeployment_auto_approveblocks withcheckconditions, attached to adeployment_groupthroughauto_approve_checks. - The separate
terraform-stacks-cliis deprecated in favor ofterraform stacks. - Beta Stacks did not count toward resources under management; at GA, Stacks RUM combines with workspace RUM for billing.
- Beta configurations and state history are no longer available after GA.

Figure 3: A Stack. Component definitions and deployment definitions combine into per-deployment state, plan and approval flow.
The conceptual win is that a Stack plans and applies components in dependency order inside the platform, with each deployment carrying its own state. Deployment groups, a Premium-tier feature, let you group deployments by environment, team or application and attach auto-approve checks. The conceptual cost is lock-in: Stacks runs in HCP Terraform and is a HashiCorp feature, not part of the open-source engine. OpenTofu does not implement it.
OpenTofu alone: workspaces, CI and discipline
OpenTofu has no built-in multi-root orchestrator. A pure OpenTofu monorepo relies on directory conventions, CI matrices and a workspace-per-environment pattern, or on a third-party platform such as Spacelift, env0, Scalr or Atlantis-style automation. That is a legitimate choice for small estates and a painful one beyond a few dozen root modules. Most teams that use OpenTofu at scale pair it with Terragrunt or with a CI platform that provides the DAG.
Worked example: counting state files and blast radius
Suppose a company runs 3 environments, 4 regions per environment, and 10 components per region (network, cluster, database, cache, queue, observability and so on). That is 3 x 4 x 10 = 120 root modules, so 120 state files. If one monolithic state held 12,000 resources, an average unit would hold 100. These counts are illustrative arithmetic, not a benchmark.
Now consider a refresh-heavy plan. If a full plan of the monolith takes 20 minutes (assumed), a per-unit plan averaging 30 seconds on 100 resources, run with concurrency 8, finishes the whole estate in roughly 120 x 30 / 8 = 450 seconds, about 7.5 minutes. A Git-diff filter that selects a change touching 3 units and 5 dependents gives 8 units x 30 seconds, about 30 seconds at concurrency 8 if they are independent, or longer if chained. The numbers show the structural point: splitting state turns a quadratic-feeling pain into a graph-selection problem. The price is that you must now manage 120 backends, 120 lock tables entries and 120 sets of outputs, which is precisely what the orchestrator automates.
Blast radius scales the same way. A bad apply in a unit that owns 100 resources can damage at most those 100 resources, plus consumers that read its outputs. A bad apply in the monolith can damage 12,000. The trade is that cross-unit refactors, such as moving a resource between units, become state surgery with moved blocks or state mv, which is risky and manual.
IaC State Management and Secrets: Where the Three Really Differ
State is the part of IaC that hurts at 3 a.m. It holds resource identifiers, dependency metadata and, unless you take care, plaintext secrets. The three options treat it differently.
What state contains and why it leaks
Every attribute a provider returns for a resource is written to state, including generated passwords, private keys and connection strings. A database resource created with a random password stores that password in the state file in clear text, even when the variable is marked sensitive, because sensitive only redacts CLI output. Anyone who can read the state bucket can read the secret. This is why backend access control, bucket encryption at rest and narrow IAM scoping are baseline controls rather than nice-to-haves.
Two newer language features attack the problem at the source. Ephemeral values and resources exist only in memory during a single phase and are never written to state or plan files. Write-only attributes let you set an argument, such as an initial administrator password, that the engine needs only at apply time and does not persist. OpenTofu shipped both in 1.11 on 9 December 2025, using a temporary SSH tunnel or short-lived credentials from a secret store as the motivating examples. Terraform has its own ephemeral and write-only mechanisms; the HashiCorp side shipped them across the 1.10 to 1.11 era, though I did not re-verify the exact versions this run. The practical consequence is the same: the migration path for secrets is to move from “generate then store in state” to “fetch ephemerally and pass write-only”.
Client-side state encryption in OpenTofu
OpenTofu documents state and plan encryption as a first-class feature. The configuration declares a key provider, an encryption method, and where to apply them. According to the OpenTofu encryption docs:
- Key providers include PBKDF2 (a passphrase of at least 16 characters), AWS KMS, GCP KMS, Azure Vault, OpenBao, an external-program provider, and an OVHcloud KMS provider maintained by OVHcloud.
aes_gcmis the only currently supported cipher method, alongsideexternalandunencrypted. Keys are 16, 24 or 32 bytes, and the docs warn of “key saturation”, recommending PBKDF2 with a strong passphrase or a KMS that rotates keys automatically.- A
fallbackblock holds the previous method so you can roll keys: OpenTofu tries the fallback only when reading with the new method fails, and always writes with the new method. enforced = trueblocks writing unencrypted data when the encryption configuration is missing.
A minimal configuration, taken from the documented example pattern:
terraform {
encryption {
key_provider "pbkdf2" "main" {
passphrase = var.passphrase
}
method "aes_gcm" "current" {
keys = key_provider.pbkdf2.main
}
state {
method = method.aes_gcm.current
enforced = true
}
}
}

Figure 4: A plan against encrypted state. The engine fetches ciphertext, obtains a data key from a key provider, and writes ciphertext back. The backend never sees plaintext.
The point of the sequence is where trust sits. With server-side encryption alone (S3 SSE, for example) anyone with read access to the object gets plaintext. With client-side encryption, a stolen bucket read yields ciphertext, and the attacker also needs access to the KMS key. That is a meaningfully smaller attack surface, at the cost of KMS availability becoming a hard dependency of every plan.
Terraform and HCP Terraform equivalents
On the HashiCorp side, state lives in HCP Terraform workspaces or Stacks deployments. HashiCorp announced Hold Your Own Key (HYOK) as generally available at HashiConf 2025, letting organizations encrypt state and plan files with their own keys before upload. So both ecosystems now offer customer-controlled encryption, but the mechanism differs: OpenTofu does it in the engine for any backend; HYOK is a feature of the commercial platform. If you run Terraform CLI against an S3 backend, you get no engine-level encryption; you rely on bucket-level controls.
What Terragrunt adds and what it does not
Terragrunt does not store state itself. It generates the backend block, can bootstrap the bucket and lock resources (the 1.0 release added a backend bootstrap command), and then delegates to the engine. So with OpenTofu underneath you inherit OpenTofu’s encryption; with Terraform underneath you inherit whatever your backend gives you. Terragrunt’s own contribution to state management is naming and uniqueness: one key per unit, derived from the directory path, which prevents the classic mistake of two root modules sharing a state key and overwriting each other.
Locking, concurrency and the lock-table trap
A state lock prevents two applies from writing the same state. Per-unit state means per-unit locks, so concurrency across units is safe, but concurrency within a unit is serialized. The failure mode is a crashed CI job that leaves a stale lock; the next run blocks until someone force-unlocks. With 120 units, stale locks become a weekly event unless CI jobs use timeouts and a cleanup step. Stacks sidesteps this by serializing runs inside the platform, which is one of the genuine operational benefits of the managed approach.
Terragrunt vs OpenTofu vs Terraform Stacks: Decision Matrix
The matrix below compares the three as you would actually combine them. Ratings are my qualitative judgment from the documented features above, not benchmarks.
| Criterion | Terragrunt + OpenTofu | Terragrunt + Terraform CLI | Terraform Stacks (HCP Terraform) |
|---|---|---|---|
| Orchestration | DAG over many units, Git-diff filtering | Same | Component graph inside one Stack |
| Multi-environment pattern | Directory per env plus stacks | Same | One configuration, many deployments |
| State per unit | One state per unit, path-derived key | Same | Per-deployment state in platform |
| Engine-level state encryption | Yes, documented providers | No, backend dependent | HYOK on platform |
| Secrets out of state | Ephemeral, write-only (1.11+) | Terraform’s own equivalents | Terraform’s equivalents |
| Vendor lock-in | Low, open source tools | Medium, BSL engine | High, Stacks is HCP only |
| Runs on your own CI | Yes | Yes | Self-hosted agents supported, control plane is HCP |
| Cost model | Free tools, you pay CI and storage | Same, plus Terraform licensing questions | Resources under management pricing |
| Learning curve | Two HCL dialects to learn | Same | New file types and concepts |
| Maturity signal | Terragrunt 1.0 stability promise | Same | GA since Sep 2025, syntax broke at GA |
When to choose which
Choose Terragrunt with OpenTofu when you want an open-source stack, run your own CI, need engine-level state encryption, and have a platform team that can own the wrapper. This is the right default for cost-sensitive estates and regulated environments that cannot send state to a SaaS.
Choose Terragrunt with Terraform CLI when you are already deeply invested in Terraform modules and HCP-adjacent tooling but want the DAG and DRY backend config without a platform migration. Check the license terms of the Terraform version you run for your use case; I am not giving legal guidance.
Choose Terraform Stacks when you already pay for HCP Terraform, your estate is a repeated pattern (the same application stamped across many regions or accounts), and you value platform-managed orchestration and approvals over portability. Stacks shines at “same components, many deployments”.
Choose plain OpenTofu with CI orchestration only for small estates, roughly under a few dozen root modules, where a Makefile or a pipeline matrix is genuinely enough.
Related reading on how GitOps controllers fit around this layer is in our ArgoCD vs Flux decision record, which covers the Kubernetes side of the same orchestration question.
Migration Walk-Through: Choosing a Path in Practice
From Terraform to OpenTofu
For a typical estate with no Stacks and no HCP-specific features, the migration is mostly mechanical: install the OpenTofu binary, run tofu init against the existing backend, review the plan for unexpected diffs, and update CI images. Lock files record provider hashes, so run tofu init -upgrade deliberately and commit the new .terraform.lock.hcl. Check that every provider you use is available from the OpenTofu registry, which mirrors the public registry for most providers. Roll one low-risk unit first, then widen. Because state file formats are compatible within feature parity, you can run both engines against different units during a transition; the danger is running both against the same unit after one of them has written a newer state version.
From beta Stacks to GA Stacks
Teams that adopted Stacks during the beta had to rename .tfstack.hcl files to .tfcomponent.hcl, rewrite orchestration rules into deployment_auto_approve plus auto_approve_checks, and fetch configuration per Stack. HashiCorp’s page states that beta configurations and state history are no longer available after GA, so any audit trail from the beta period must be exported beforehand. The lesson for adopters is to treat a vendor’s “GA with backward compatibility on APIs” as an API promise, not a promise that language syntax is frozen; the GA move was a breaking syntax change.
From Terragrunt 0.x to 1.0
Gruntwork says 1.x will not break CLI flags, HCL configuration or stable outputs. The migration work is therefore concentrated in the 0.x to 1.0 jump: replacing run-all with run, dropping the --terragrunt- prefix, and replacing the seven legacy selection flags with --filter. Gruntwork also says users on versions older than 0.89.0 see the largest performance gains. A pragmatic path is to upgrade through the last 0.x releases first, fix deprecation warnings, then step to 1.0 and run find and list to compare the unit inventory before and after.
Introducing explicit stacks in Terragrunt
Terragrunt stacks generate units from a terragrunt.stack.hcl file so that a repeated pattern (the same twelve units per region) is defined once with different values. The generated units land in a hidden stack directory and are then run like ordinary units. The recommendation in the 1.0 post is to prefer stacks for higher-level patterns, and there is a migration guide from the older layout. Because I could not retrieve the detailed stack reference this run, consult the official docs for block syntax before you adopt it; the structural idea is “define the pattern once, instantiate it with values”.
A rollout order that limits risk
- Inventory current root modules and count state files; compute the dependency graph.
- Pick the engine first (OpenTofu or Terraform), because it affects every later choice.
- Introduce an orchestrator on one non-production environment.
- Turn on state encryption or HYOK before widening, since retrofitting encryption on a large estate is easier with a
fallbackwindow. - Move secrets to ephemeral and write-only patterns unit by unit.
- Add Git-diff filtering to CI to cut plan time, then measure actual plan durations rather than trusting estimates.
Trade-offs, Gotchas, and What Goes Wrong
The wrapper tax. Terragrunt adds a second configuration language surface. Engineers must understand terragrunt.hcl semantics (include merging, dependency evaluation, find_in_parent_folders) on top of module HCL. Misreading include order is a classic source of “why did this unit get the wrong region” bugs. The tax is worth paying above roughly fifty units and often not below it.
Mock outputs hide real breakage. Terragrunt dependencies can supply mock_outputs so that plan works before the dependency is applied. If mocks drift from real output shapes, a plan succeeds and the apply fails mid-run, leaving a partial rollout. Treat mocks as test fixtures and validate them in CI against real outputs.
Cross-unit dependency cycles. Splitting state makes it easy to create a logical cycle across units, for example a network unit that needs a DNS zone ID from a unit that in turn needs a load balancer address from the network. The DAG runner will refuse the cycle, but refactoring out of one is state surgery. Design layers (foundation, platform, application) up front and allow dependencies to point only downward.
State surgery risk. Moving resources between units requires moved blocks or state mv against two backends. A mistake can orphan a resource, causing the next apply to try to create a duplicate or destroy a live one. Always run in a plan-only mode first and keep state backups through bucket versioning.
Stacks lock-in and billing. Stacks lives in HCP Terraform and is billed through resources under management, combined with workspace RUM at GA. A large estate that is cheap to run on your own CI can become expensive in a managed model. Model the RUM count before committing, using the current vendor pricing page, which I did not verify here. Also note that Stacks syntax changed at GA, so expect further evolution.
Encryption key as single point of failure. Client-side state encryption is only as available as the key provider. If a KMS key is deleted or a passphrase is lost, the state is unrecoverable ciphertext. Use fallback for rotation, keep key deletion protection on, and back up state before enabling encryption. The docs also note that a short or weak PBKDF2 passphrase undermines the scheme.
Engine divergence. OpenTofu and Terraform are drifting apart in features. A module written with OpenTofu’s enabled lifecycle argument will not parse in Terraform, and vice versa for Terraform-only features. If you publish shared modules, pin required versions and test on both engines, or commit to one.
Provider cache and concurrency memory. Running many units concurrently multiplies provider process memory, since each plan spawns provider binaries. Terragrunt 1.0 auto-configures a shared provider cache for OpenTofu 1.10 and later to cut repeated downloads, but concurrency still needs to be sized to CI runner memory. Start low and raise it while watching runner out-of-memory kills.
Partial apply and the failure budget. In a multi-unit run, one unit failing leaves earlier units applied. The orchestrator does not roll back. Plan for forward fixes, keep units small so a failure’s scope is small, and use run reports (Terragrunt 1.0 offers JSON and CSV reports) to see exactly which units succeeded.
Practical Recommendations
The recommendation depends on three facts about your organization: how many root modules you manage, whether you already pay for HCP Terraform, and whether you can send state to a SaaS.
If you manage fewer than about thirty root modules, stay with a single engine and a CI matrix; adding an orchestrator now is overhead. If you manage more than fifty, adopt an orchestrator, because backend boilerplate and ordering bugs will cost more than the learning curve. If you are open-source-first or regulated, the combination of Terragrunt and OpenTofu gives you engine-level state encryption, no per-resource pricing and a stability promise from the Terragrunt 1.0 line. If you already run HCP Terraform and your estate is a repeated pattern, evaluate Stacks seriously, but pilot on a non-critical application because the GA syntax change shows the feature is still maturing.
Whatever you pick, do the unglamorous controls first: versioned and access-controlled state buckets, locking, encryption, and secrets that never touch state.
Checklist before you commit:
- [ ] Count root modules and compute the expected number of state files.
- [ ] Decide the engine (OpenTofu or Terraform) before the orchestrator.
- [ ] Enable bucket versioning and least-privilege access on the state backend.
- [ ] Turn on state encryption (OpenTofu) or HYOK (HCP Terraform) with a rotation plan using
fallback. - [ ] Replace generated-secret-in-state patterns with ephemeral and write-only attributes.
- [ ] Add Git-diff-based selection to CI and measure plan duration before and after.
- [ ] Pin engine and Terragrunt versions in CI and in a
.tool-versionsor equivalent file. - [ ] Validate
mock_outputsagainst real outputs in a scheduled job. - [ ] Write a runbook for stale locks and for partial multi-unit failures.
- [ ] If choosing Stacks, model RUM cost with current vendor pricing and export audit history.
Frequently Asked Questions
Is Terragrunt a replacement for OpenTofu?
No. Terragrunt is a wrapper that invokes OpenTofu or Terraform. It generates backend and provider configuration, orders many root modules by dependency, and selects which ones to run. You still need an engine underneath. The “terragrunt vs opentofu” framing is really “which orchestrator, and which engine beneath it”, and the two are commonly used together, with Terragrunt auto-configuring a shared provider cache when OpenTofu is 1.10 or later.
Can OpenTofu run Terraform Stacks?
Based on HashiCorp’s documentation, Stacks is a feature of HCP Terraform and the terraform stacks command, with .tfcomponent.hcl and .tfdeploy.hcl files. I found no evidence that OpenTofu implements Stacks. If you want the same “components times deployments” pattern on OpenTofu, the closest open-source equivalent is Terragrunt’s explicit stacks, which generate units from a stack file. Verify against current OpenTofu release notes before relying on this.
Is OpenTofu a drop-in replacement for Terraform?
For most configurations that use shared features, yes: you swap the binary, re-run init and review the plan. It is not a guaranteed drop-in because the engines have diverged. OpenTofu 1.11 added the enabled lifecycle argument and its own ephemeral handling, and Terraform has features such as Stacks that OpenTofu lacks. Test your modules on the target engine, check your providers are available in its registry, and migrate one unit first.
How should I manage secrets in IaC state?
Assume anything a provider returns ends up in state in plaintext, and sensitive only hides CLI output. Reduce exposure three ways: use ephemeral resources and write-only attributes so secrets never reach state, encrypt state client-side (OpenTofu’s key providers or HCP Terraform’s HYOK), and lock down backend access with least privilege and versioned buckets. Prefer secret managers that mint short-lived credentials at apply time.
What changed in Terragrunt 1.0?
Announced 30 March 2026, it promises backward compatibility across 1.x for CLI flags, HCL configuration and the serialized output of find and Run Reports. It renamed run-all to run, removed the --terragrunt- flag prefix, unified selection under --filter, added Run Reports, find, list, exec and backend bootstrap, and recommends stacks for higher-level patterns. Migration from 0.x is where the breaking changes sit.
Which is cheapest at scale?
Terragrunt plus OpenTofu has no tool licensing cost; you pay for CI minutes, runner memory and state storage. Terraform Stacks is priced by resources under management in HCP Terraform, and at GA Stacks RUM combines with workspace RUM. Which is cheaper depends on resource count, apply frequency and your CI cost, so compute your RUM against the current price sheet rather than assuming either way.
Further Reading
Internal:
- Terraform vs Pulumi vs Crossplane: IaC comparison
- ArgoCD vs Flux: GitOps decision record
- Platform engineering, golden paths and Crossplane maturity
- Model predictive control in industrial digital twins, a useful parallel for how constraint-driven orchestration thinking carries over to industrial systems
External:
- Terragrunt 1.0 announcement, Gruntwork
- OpenTofu state encryption documentation
- Terraform Stacks beta-to-GA update, HashiCorp Developer
By Riju — about
