Tools for managing infrastructure across environments and accounts without a Terragrunt layer, from Terraform orchestrators to replacing the Terraform code itself.
Terragrunt is a wrapper around Terraform and OpenTofu that keeps configuration DRY across environments and accounts, by generating backend and provider blocks, passing inputs to shared modules and running root modules in dependency order with run --all. It is useful once a repository has a dozen environment folders that differ by a few variables, and it gets harder to work with as the terragrunt.hcl files, include chains and dependency blocks become a second configuration language that only one or two people on the team can debug, with mocked outputs in plans that hide what will really change. This article compares the tools teams tend to move to, which are Encore, Terramate, Atmos, Terraform Stacks, plain Terraform or OpenTofu and Pulumi. For how Terragrunt itself works next to Terraform, see Terragrunt vs Terraform.
Reasons teams look for Terragrunt alternatives:
include and dependency blocks make it hard to see which values a module actually receives.run --all across many modules is slow and fails in ways that are hard to retry partially.Encore combines the application and its infrastructure in one codebase, so the Postgres databases, Pub/Sub topics, buckets, cron jobs and secrets a service needs are declared in TypeScript or Go, encore run starts them locally (Postgres runs in Docker), and each environment you create gets the same resources provisioned in your own AWS or GCP account. Encore takes the place of the Terraform modules for that application infrastructure rather than running alongside them, which removes the per-environment folders, backends and dependency blocks that Terragrunt exists to manage.

A Terragrunt setup for one service often has a terragrunt.hcl per environment that includes a root config and points at a shared module:
# live/prod/orders-db/terragrunt.hcl
include "root" {
path = find_in_parent_folders("root.hcl")
}
terraform {
source = "../../../modules/rds"
}
dependency "vpc" {
config_path = "../vpc"
}
inputs = {
name = "orders"
subnet_ids = dependency.vpc.outputs.private_subnet_ids
}
In Encore the same database, plus the queue and bucket the service uses, is declared once in Go next to the code that uses it, and every environment gets its own copy:
package orders
import (
"encore.dev/pubsub"
"encore.dev/storage/objects"
"encore.dev/storage/sqldb"
)
var db = sqldb.NewDatabase("orders", sqldb.DatabaseConfig{
Migrations: "./migrations",
})
type OrderPlaced struct{ OrderID int64 }
var Placed = pubsub.NewTopic[*OrderPlaced]("order-placed", pubsub.TopicConfig{
DeliveryGuarantee: pubsub.AtLeastOnce,
})
var Receipts = objects.NewBucket("receipts", objects.BucketConfig{
Versioned: false,
})
encore run, which Terraform and Terragrunt do not cover at all.terragrunt.hcl to add for each environment.Encore covers the infrastructure your application uses, and resources outside that scope, such as organization-level IAM, DNS zones you manage elsewhere or a data warehouse, stay where they are today. Moving an existing service means adopting the Encore SDK in TypeScript, Go, Python or Rust, and teams usually start with one service.
Run in your terminal to get started locally.
TerramateTerramate organizes a repository into stacks, generates repeated backend and provider blocks from shared globals and runs commands only in the stacks that a Git change touched.
Terramate is the closest replacement for Terragrunt's orchestration, and the Terraform it runs is still yours to write and maintain for every environment.
Atmos treats Terraform root modules as components and describes which components run in which account, region and environment in YAML stacks that import shared catalogs and override only what changes.
atmos describe affected lists the stacks a change touches.Atmos suits platform teams that manage many accounts, and the YAML inheritance model and its conventions take time to learn for a team with three environments.
Terraform Stacks group several modules as components and repeat them as deployments for each environment, account or region, managed as one unit in HCP Terraform.
Stacks run in HCP Terraform and are not available on legacy HCP Terraform team plans, and HashiCorp documents limits such as 20 deployments and 100 components per Stack.
Many teams drop the wrapper and use shared modules with one small root module per environment, run in order by their CI pipeline. OpenTofu also accepts variables in backend configuration, which removes one of the main reasons for generating backends.
# environments/prod/main.tf
module "orders_db" {
source = "../../modules/rds"
name = "orders"
subnet_ids = module.vpc.private_subnet_ids
}
The duplication Terragrunt removed comes back in small amounts, mainly provider and backend blocks per environment, which is manageable for a handful of environments. The Terraform alternatives guide covers options that go further.
Pulumi describes infrastructure in TypeScript, Python, Go, C# or Java, and each environment is a stack with its own configuration file, so loops and functions take the place of Terragrunt's generation.
Pulumi replaces Terraform as well as Terragrunt, which makes it a migration rather than a wrapper swap, and the infrastructure code still lives apart from the application code it supports.
Terragrunt solves the duplication that comes from describing the same infrastructure for every environment, and the orchestrators above solve it in other ways, while Encore takes the application part of that infrastructure out of the Terraform and into the application code.
Terramate if you want change detection and code generation while keeping plain Terraform or OpenTofu, Atmos for YAML stacks across many accounts and regions, Terraform Stacks if you use HCP Terraform, and Pulumi for environments as code in a general-purpose language. Encore replaces the Terraform code for application infrastructure, so there is no multi-environment Terraform to orchestrate.
Less than it used to be. OpenTofu now allows variables in backend configuration, and Terramate, Atmos and Terraform Stacks cover orchestration in other ways. Terragrunt is still useful for large estates with many root modules and explicit dependencies between them.
Terragrunt wraps Terraform and runs it with its own configuration files that generate backends, inputs and dependencies. Terramate generates plain Terraform code and orchestrates runs across stacks with Git-based change detection, so the code it produces can be used without Terramate.
Yes. Modules, workspaces or one root module per environment, and a CI pipeline that runs them in order cover many setups. The cost is some repeated backend and provider configuration that Terragrunt would otherwise generate.
Encore reads the databases, Pub/Sub topics, buckets and cron jobs declared in TypeScript, Go, Python or Rust code and provisions them in each environment in your own AWS or GCP account. Each environment gets the same resources from the same code, so there are no per-environment Terraform modules or Terragrunt files for application infrastructure.
Declare them in Go with Encore's SDK, using sqldb.NewDatabase for Postgres, pubsub.NewTopic for Pub/Sub and objects.NewBucket for storage, next to the code that uses them. encore run starts them locally, and every environment gets the same resources provisioned in your own AWS or GCP account, with no Terraform modules or Terragrunt files for them.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.