Why I Use Terragrunt Over Terraform/OpenTofu in 2025
Terragrunt vs Terraform: Why I chose Terragrunt to eliminate code duplication, automate state management, orchestrate deployments, and follow pattern-level reuse.
OpenTofu/Terraform is painful to deal with on large infrastructures.
Code duplication, manual backend setup, and orchestration gets worse when your codebase grows.
Terragrunt is a wrapper over OpenTofu/Terraform that solves these issues, but has a negative reputation.
I think this reputation is based on outdated information and misconceptions.
The new Terragrunt Stacks feature is game-changing.
It enables pattern-level infrastructure re-use. Something I’ve never seen before.
In 2025, most pain points of Terragrunt adoption are solved.
If you’ve managed OpenTofu/Terraform across multiple environments, you know the pain: massive code duplication between dev, staging, and prod.
Manual backend state configuration. No built-in orchestration. Custom CI/CD scripts that break at the worst moments.
Luckily, I tried Terragrunt some years ago. I’m so glad I did!
It’s a wrapper over OpenTofu/Terraform to avoid code duplication and orchestrate your OpenTofu/Terraform modules.
I use it in all my projects now, and I’ll never go back.
Yet, when I discuss the “Terragrunt vs OpenTofu/Terraform” topic with my peers on LinkedIn and Reddit, I’m always surprised by Terragrunt’s bad reputation.
It really doesn’t reflect my own experience at all. So I dug deeper to understand why people have such a negative feeling about it.
And guess what I found? Most of it stems from misconceptions and outdated knowledge from earlier versions.
In 2025, most of Terragrunt’s pain points have been addressed, and some game changer features have been released.
In this article, I’ll cover the following to explain why I chose Terragrunt over OpenTofu/Terraform:
For managing multiple environments with OpenTofu/Terraform, there are two possibilities:
Using folder duplication.
Using OpenTofu/Terraform Workspaces.
Let’s start with the first option.
In this scenario, you would build your OpenTofu/Terraform modules under the modules directory and create one directory per environment (dev, staging, and prod).
Each main.tf instantiates the vpc module. You can directly see the problem here: we need to redefine provider.tf, backend.tf, variables.tf, and outputs.tf in each environment folder.
That’s a lot of duplication! Any change to shared configuration needs to be manually copied to every environment.
Manual Backend State Setup
Following the example from the previous section, you would also need to write the backend configuration for each environment:
You will also need to create the S3 bucket manually before anyone can run terraform init or tofu init.
Usually, this means running a separate OpenTofu/Terraform configuration just for the backend infrastructure, or clicking through the AWS console.
The whole process becomes a headache that only gets worse as you add more environments and team members.
You got it right! Each time you need to create an additional environment, you’ll need to copy and paste an environment folder and manually change all the keys.
No Built-in Orchestration
OpenTofu and Terraform CLI can only work on one directory at a time. It has no idea that your modules depend on each other.
Here’s a typical application stack:
dev/├── vpc/ # Must deploy FIRST├── database/ # Must deploy SECOND (needs VPC) ├── app-servers/ # Must deploy THIRD (needs database)└── load-balancer/ # Must deploy FOURTH (needs app servers)
To deploy this stack, you have to manually run commands in dependency order:
cd dev/vpc &&terraform applycd ../database &&terraform apply cd ../app-servers &&terraform applycd ../load-balancer &&terraform apply
Following such an error-prone process in a production environment is not realistic.
Many teams think CI/CD pipelines will elegantly solve these OpenTofu/Terraform limitations. I don’t believe it, and I’ll explain you why.
You still need custom scripts to handle orchestration logic. CI/CD just moves the complexity into your YAML pipeline:
name: Deploy Infrastructurejobs:deploy:steps:-run: cd environments/dev/vpc && terraform apply -auto-approve-run: cd ../database && terraform apply -auto-approve -run: cd ../app-servers && terraform apply -auto-approve-run: cd ../load-balancer && terraform apply -auto-approve
Using this solution, we port the orchestration logic in YAML instead of using purpose-built tools.
Unfortunately, we still have all the problems we discussed earlier:
Copy-paste directory structures
Manual backend configuration
No native dependencies between modules
Here’s another tedious scenario: when adding a new module or changing the dependencies, you need to rewrite your custom orchestration scripts manually.
I think CI/CD is excellent for deployment automation, but it’s the wrong approach for solving the architectural flaws of OpenTofu/Terraform.
We’re simply adding another layer of complexity on top of the already existing problems.
Terraform Workspaces Are Flawed
Terraform Workspaces (or OpenTofu Workspaces) let you create separate state files for the same codebase. Each workspace maintains its own state while sharing the same configuration files.
Many engineers use this feature as a way to maintain a single configuration and change the backend’s state file path according to the workspace.
HashiCorp themselves don’t recommend this practice in their official documentation:
“Workspaces alone are not a suitable tool for system decomposition because each subsystem should have its own separate configuration and backend.” (source)
Workspaces only change state file names. They don’t solve the architectural problems we’ve been discussing.
Additionally, you’re not able to make your environment configurations diverge. For example, you need to use the same instances across dev and prod. In realistic scenarios, you’ll want to create smaller machines during development.
It’s also easy to forget that you’re not in your dev workspace anymore and inadvertently affect your prod environment.
Terraform Cloud? Not Always the Solution
Terraform Cloud Pricing: resource ramp-up very quickly with multi-environment setups | source: HashiCorp
Terraform Cloud Pricing: resource ramp-up very quickly with multi-environment setups (source)
Terraform Cloud (TFC) is HashiCorp’s paid, proprietary platform. For teams focused on open-source tooling, this immediately rules it out.
HashiCorp has introduced Terraform Stacks to address some orchestration concerns.
Stacks can help manage dependencies between components and reduce some of the manual coordination we’ve been talking about.
However, Stacks is still in beta, has limited deployment options (500 resources max), and requires expensive tiers for full access.
Terraform Cloud adds collaboration features and a web UI.
From my experience, it makes sense to invest in TFC when collaboration becomes a real need, especially for large DevOps teams.
For teams with less than 10 engineers, I think sticking to Terragrunt is a sound move: you get the same orchestration benefits without the vendor dependency or per-resource costs.
Terragrunt for Production in 2025
I don’t get excited about many tools, but Terragrunt genuinely transformed how I manage Infrastructure as Code.
Terragrunt is a wrapper over OpenTofu/Terraform that tackles its limitations.
After dealing with all the problems I just described, it solved every major pain point in a way that felt elegant and maintainable.
To be clear, the discussion is not really “Terragrunt (TG) vs Terraform (TF)” but rather “native TF vs (TF + TG)”. As TG uses TF under the hood.
Let’s jump right into how it addresses each issue we’ve covered.
The dev environment would be identical except env = "dev" and only one availability zone, for example azs = ["us-west-2a"].
include blocks let child configurations inherit everything from the parent. Terragrunt automatically generates the provider.tf file in each environment:
terraform { required_providers { aws = { source ="hashicorp/aws" version ="~> 5.0" } }}provider "aws" { region ="us-west-2"}
It prevents the duplication of the OpenTofu/Terraform version, the AWS provider version, and the provider block.
Supports Automated Backend State Isolation
Remember the manual backend configuration nightmare from earlier? Terragrunt eliminates all of that.
You define the backend configuration once in your root.hcl file, and Terragrunt automatically handles unique state isolation for each environment:
It literally does the coffee for you: Terragrunt automatically creates the S3 bucket and DynamoDB table if they don’t exist.
No more bootstrap scripts or clicking manually on the AWS console!
The path_relative_to_include() function automatically generates unique S3 keys based on the directory structure.
Your prod environment produces prod/terraform.tfstate, while dev generates dev/terraform.tfstate. No manual key configuration, no copy-paste backend files!
Unlike OpenTofu/Terraform’s backend blocks, Terragrunt can use dynamic values and local variables in backend configuration.
You write the backend setup once, and it works correctly across all environments without any manual intervention.
Has Built-in Orchestration
Remember the custom CI/CD scripts and manual orchestration from earlier? Terragrunt eliminates that entirely with native dependency management.
Unit: A Terragrunt wrapper around a OpenTofu/Terraform module. Defines a single, deployable piece of infrastructure.
Stack: Defines a collection of related units that can be reused.
Making The Example Even DRYer
In the previous example, we still had to copy Terragrunt configurations in each environment directory. prod/app/terragrunt.hcl and dev/app/terragrunt.hcl were still duplicated.
With Terragrunt Stacks, we can factorize that too!
We’ll use the following two repositories:
An infrastructure-catalog repository where our OpenTofu/Terraform modules and units will live:
First, we moved live/prod/app/terragrunt.hcl and live/prod/database/terragrunt.hcl from the project/ tree into the units directory inside the infrastructure-catalog repository without changing their content. All units will be defined once in this directory.
Next, we define the pattern (app + database) once in a stack file in the infrastructure-live repository:
prod and dev are exactly identical. That’s right! Because our units search for the env.hcl file in parent directories, we don’t even have to specify the environment.
You can even point your dev stack to a more recent version v1.0.1 and keep prod on a stable one.
This is already a significant improvement. We’ve eliminated the last bits of duplication.
But honestly, I thought this was just a nice incremental upgrade.
I was wrong.
Nested Stacks
Nested Terragrunt Stacks example | source: Gruntwork
Here’s what I didn’t expect: Terragrunt Stacks can be nested.
For example, you could re-use your web-app stack and add a monitoring stack to it.
Gruntwork is planning to incorporate the ability to use stack outputs as dependencies in the future. This will allow for even greater modularity.
Then it clicked: this isn’t just about eliminating copy-paste anymore.
Pattern Level Re-Use
This is the fundamental shift I completely missed at first.
With this new feature, platform teams aren’t just sharing OpenTofu/Terraform modules anymore. They’re packaging and distributing complete infrastructure patterns.
Want to deploy a new microservice? Don’t think about databases, load balancers, monitoring, and networking separately. Just reference the microservice pattern and input your application-specific values.
Need a data pipeline? Reference the data pipeline pattern. It comes with ingestion, processing, storage, and observability already wired together.
Imagine the possibilities: creating a reusable stack that you could easily incorporate into your client’s infrastructures.
I’ve never had performance issues deploying and maintaining multiple environments with thousands of resources.
Objection 3: Difficult Debugging
Coming from OpenTofu/Terraform, people may find the debugging process more difficult because Terragrunt has longer traces. It applies the infrastructure following a Directed Acyclic Graph (DAG).
I think it is certainly easier to debug than the custom CI/CD workflows needed to work around OpenTofu/Terraform’s caveats.
Why I Think These Trade-offs Are Worth It
Look, I’m not going to pretend Terragrunt has zero learning curve or that every team should adopt it.
But when I see a 2025 article from Scalr ranking #1 on Google for Terragrunt drawbacks, I’m baffled to find that all the highlighted problems have been resolved since 2021-2022.
Unfortunately, this leads people to make decisions based on outdated information.
At the time of the writing, Terragrunt has 215 open issues versus 2,350 closed issues. That’s pretty solid for an open-source project.
Bottom line: for teams managing multiple environments with orchestrated deployments, I think Terragrunt is absolutely worth it.
Terraform vs Terragrunt: Comparative Feature Matrix
Here’s my attempt at building a Terragrunt versus Terraform table:
Dimension
Terragrunt v0.80+
OpenTofu/Terraform
Workflow Simplicity
High: One command deploys an entire stack of modules defined in one file.
Low: Requires manual scripts or CI workflows to coordinate multiple modules.
Code Duplication
Low: Hierarchical configs via include blocks. Stacks eliminate copy-paste across environments. Modules reused without duplication.
High: Module reuse exists, but backend/provider configs must be duplicated.
Dependency Handling
Automatic: Built-in dependency graph with dependency blocks.
Manual: No inter-module automatic dependencies.
State Isolation
Strong: Enforces one state per module. Auto-calculates unique remote state keys. Can auto-create backends. Small blast radius.
Manual: State keys must be split manually. Large modules risk huge blast radius.
Performance
Moderate: v0.80 delivered 42% faster execution. Still adds overhead, but now acceptable.
Baseline: No wrapper overhead.
Testability
Moderate: Works with Terratest. Can capture plan outputs for validation. No built-in test framework.
High: Has provider mocking. Otherwise same testing approaches as Terragrunt.
Learning Curve
High: Must learn Terragrunt syntax. Initial training investment needed, but day-to-day usage becomes simpler.
Low: Most DevOps engineers are already familiar with Terraform.
Community
Moderate: Active, engaged community with responsive maintainers.
Low: Integration with Atlantis is not trivial. Digger seems like a promising OSS alternative. For enterprise features, Gruntwork Pipeline has been designed for Terragrunt.
High: Supported by most (if not all) TACOS platforms.
Terragrunt dominates features-wise (workflow, DRY, dependencies, state isolation) while Terraform/OpenTofu wins on familiarity, simplicity, performance, and TACOS support.
Final Takeaway
I’ll be honest, Terragrunt has genuinely made my infrastructure experience easier and more enjoyable.
When I read people complain about Terragrunt being “too complex” or “over-engineered,” I’ve realized they’re usually thinking about the 2019 version or relying on misconceptions.
What happened in 2025 changed the entire conversation.
Terragrunt evolved from a DRY orchestration tool to a pattern-level infrastructure platform. Meanwhile, OpenTofu and Terraform remained focused on component-level management.
Even before Stacks, I used to rely on Terragrunt instead of OpenTofu/Terraform for reducing duplication and orchestration. Now? They’re solving different problems entirely.
Terragrunt isn’t right for everyone. If you’re managing a single environment with few resources, native OpenTofu/Terraform is probably fine. If you’re a small team that deploys infrastructure once a month, the learning curve might not be worth it.
But if you’re managing multiple environments, writing custom module orchestration, or constantly copying configuration between folders? Terragrunt solves this problem.
That’s exactly why I wrote this article. In the hope you find the same benefits in Terragrunt that I’ve found myself.
Give it a try, I’d love to hear about your experience!
Stay in touch
I hope you enjoyed this article as much as I enjoyed writing it!
Feel free to DM me any feedback on LinkedIn or email me directly. It will be highly appreciated.
That's what keeps me going!
Subscribe to get the latest articles from my blog delivered straight to your inbox!
About the author
Axel Mendoza
Senior MLOps Engineer
I'm a Senior MLOps Engineer with 6+ years of experience building production-ML systems.
I write long-form articles on MLOps to help you build too!