Migrating from Terragrunt
Terragrunt and Atmos solve similar problems—managing Terraform at scale with DRY configurations. If you're coming from Terragrunt, this guide will help you understand the differences and migrate your infrastructure.
Key Differences at a Glance
| Concept | Terragrunt | Atmos |
|---|---|---|
| Configuration Format | HCL (terragrunt.hcl) | YAML (.yaml) |
| Reuse Mechanism | include {} blocks | import: with deep merge |
| Dependencies | dependency blocks | dependencies.components for ordering and !terraform.output for values |
| Variable Passing | inputs = {} | vars: with inheritance |
| Locals | locals {} | locals |
| Module Source | terraform { source = "..." } | source: for JIT provisioning or vendor.yaml for vendoring |
| CLI | terragrunt plan/apply | atmos terraform plan/apply |
| Hooks | before_hook, after_hook, error_hook | hooks |
| State Backend | remote_state with backend creation | Centralized backend config with provision.backend |
| Environments | Directory structure | Stack files (YAML) |
| Units | Directory with terragrunt.hcl | Component instance in a stack |
| Stacks | Collection of units (terragrunt.stack.hcl) | Stack file (e.g., prod.yaml) |
What Atmos Has That Terragrunt Doesn't
Beyond the conceptual differences, Atmos provides several capabilities that don't exist in Terragrunt:
| Feature | Description |
|---|---|
| Native Authentication | Built-in multi-cloud auth with SAML, SSO, OIDC, and GitHub Actions. No separate tools needed—atmos auth login handles it all. |
| Vendoring | Pull and version external modules locally with atmos vendor pull. Customize vendored code while tracking upstream. |
| Custom Commands | Define your own CLI commands in YAML. No scripting needed—integrate team-specific workflows directly into Atmos. |
| Workflows | Orchestrate multi-step operations across components and stacks. Chain commands, add conditions, run in parallel. |
| Terraform Shell | atmos terraform shell vpc -s prod drops you into a configured shell for native Terraform debugging. All vars and backend pre-configured. |
| Affected Detection | atmos describe affected analyzes Git changes to find impacted components—purpose-built for CI/CD. |
| Component Validation | JSON Schema and OPA policy validation for stack configurations before deployment. |
| Stack Describe | atmos describe component shows the fully-resolved configuration for any component in any stack. |
| Configuration Provenance | atmos describe component --provenance traces where every value came from across the import hierarchy. |
Directory Structure Comparison
- Terragrunt
- Atmos
Terragrunt uses HCL syntax for configuration, which might feel familiar if you're accustomed to Terraform—but it can also be confusing since it's not actually Terraform code. You're writing HCL that looks like Terraform but behaves differently, with proprietary functions like find_in_parent_folders() and dependency blocks that don't exist in Terraform.
infrastructure/
├── terragrunt.hcl # Root config (HCL, not Terraform)
├── _envcommon/
│ ├── vpc.hcl # Shared config (HCL, not Terraform)
│ └── eks.hcl
├── prod/
│ ├── us-east-1/
│ │ ├── vpc/
│ │ │ └── terragrunt.hcl # More HCL config
│ │ └── eks/
│ │ └── terragrunt.hcl
│ └── terragrunt.hcl
└── dev/
└── us-east-1/
├── vpc/
│ └── terragrunt.hcl
└── eks/
└── terragrunt.hcl
Characteristics:
- HCL config files scattered across directories
- Environment structure baked into folder hierarchy
- Each component needs its own
terragrunt.hcl - Easy to confuse Terragrunt HCL with actual Terraform code
With Atmos, the distinction is clear: YAML for configuration, Terraform for code. Your stack configurations are pure YAML—no Terraform domain knowledge required—while all components are native Terraform modules, unchanged and portable.
infrastructure/
├── atmos.yaml # Atmos config (YAML)
├── components/
│ └── terraform/
│ ├── vpc/
│ │ ├── main.tf # Native Terraform
│ │ └── variables.tf # Native Terraform
│ └── eks/
│ ├── main.tf
│ └── variables.tf
└── stacks/
├── _defaults/
│ ├── globals.yaml # Shared defaults
│ └── vpc-defaults.yaml
├── dev/
│ ├── us-east-1.yaml # Dev in us-east-1
│ └── us-west-2.yaml # Dev in us-west-2
├── staging/
│ └── us-east-1.yaml # Staging in us-east-1
└── prod/
├── us-east-1.yaml # Prod in us-east-1
└── us-west-2.yaml # Prod in us-west-2
Atmos supports many design patterns for organizing your stacks—from simple flat structures for startups to enterprise-scale patterns with multi-tenant, multi-region hierarchies. Choose the pattern that fits your needs and evolve as you grow.
Characteristics:
- Code (Terraform) and config (YAML) cleanly separated
- One stack file per environment—no per-component config files
- Components are native Terraform—work with or without Atmos
- Anyone can read YAML; no HCL knowledge needed
Key difference: Atmos cleanly separates components (native Terraform code) from stacks (YAML configuration). With Terragrunt, HCL configuration files are scattered throughout your directory structure alongside—and sometimes confused with—actual Terraform code.
Atmos philosophically treats the filesystem as organization only—it doesn't influence behavior. All configuration semantics live in YAML stack files and their imports. This means:
- You can query any component's fully-resolved configuration with
atmos describe component - You can trace where any value came from with
atmos describe component --provenance - You can output configuration as JSON/YAML for tooling integration
- Directory structure is purely for human organization, not runtime behavior
This is fundamentally different from Terragrunt, where the directory hierarchy is the configuration—path_relative_to_include() and find_in_parent_folders() derive meaning from filesystem location.
Concept Mapping
If you're familiar with Terragrunt, the concepts below will help you translate what you already know into Atmos equivalents. Each section shows a side-by-side comparison so you can see exactly how Terragrunt patterns map to Atmos.
Include → Import
- Terragrunt
- Atmos
Terragrunt uses include blocks with proprietary functions like find_in_parent_folders() to locate and merge parent configurations. You must specify whether to expose included values, and the path resolution can be complex with nested directory structures.
Atmos uses simple import statements—just list the files you want to include. All imports are automatically deep-merged in order, with later values overriding earlier ones. No special functions or expose flags needed.
Dependency → Remote State
- Terragrunt
- Atmos
Terragrunt uses dependency blocks to reference outputs from other modules. You specify a relative path to the dependent module's directory, and Terragrunt reads its state file to extract outputs. This creates implicit ordering and requires the dependency to be applied first. Since it's all HCL, the line between "configuration" and "business logic" can blur—you're writing code that looks like Terraform but isn't.
Atmos separates dependency ordering from value lookup. Use dependencies.components to declare explicit component ordering, and use !terraform.output to read outputs from another component's remote state.
Because Atmos uses YAML for configuration and keeps Terraform for code, there's a clear separation: stacks are configuration, components are code. Your configuration (what to deploy, with what values) stays in YAML. Your business logic (how resources are created) stays in Terraform. This separation makes it easier to reason about your infrastructure.
Inputs → Vars
- Terragrunt
- Atmos
Terragrunt passes variables to Terraform using the inputs block. These values become -var arguments when Terraform runs. The inputs block uses HCL syntax with equals signs and curly braces.
Atmos uses the vars section under each component. Variables are defined in YAML and automatically passed to Terraform. You can define vars at multiple levels (global, component) and they deep-merge, allowing inheritance and overrides.
Terraform Source → Component + Vendoring
- Terragrunt
- Atmos Source Provisioning
- Atmos Vendoring
Terragrunt specifies the Terraform module source directly in each terragrunt.hcl file. The source is fetched at runtime, and you manage versions by changing the ref parameter. Each environment directory needs its own copy of this source reference.
Atmos source provisioning is the closest equivalent to Terragrunt's terraform.source: declare the remote module source in stack configuration, and Atmos fetches it when the component runs.
Then run Terraform normally. Atmos automatically provisions the source before Terraform runs:
atmos terraform plan vpc --stack prod
You can also pull the source explicitly when you want to prefetch or refresh it manually:
atmos terraform source pull vpc --stack prod
The ttl setting is an Atmos-specific addition that controls when cached sources are refreshed, which is especially useful for floating refs like branches. Set ttl: "0s" to disable source caching and pull every time. Terragrunt does not provide an equivalent source cache TTL.
Workdir provisioning is strongly recommended with source provisioning. It stages each component instance under .workdir/, so Terraform runs with isolated .terraform/ directories, generated varfiles, and backend files.
Atmos vendoring is the workflow for explicitly pulling a local copy of remote module code. Define sources in vendor.yaml, pull them with atmos vendor pull, and reference the local component in stacks. Teams often use this when they want vendored code committed for review, auditability, offline use, or local customization.
First, define the vendor source:
Then pull it: atmos vendor pull
Finally, reference in your stack:
Generate Blocks → Code Generation
- Terragrunt
- Atmos
Terragrunt uses generate blocks to create arbitrary files before Terraform runs. You write file contents as heredoc strings within HCL, specifying the path and overwrite behavior. This gives you full templating power, but that flexibility comes with complexity—you're essentially writing a code generator in HCL.
Atmos supports declarative file generation with the generate section. This is the closest equivalent to Terragrunt generate blocks: define the files in YAML, and Atmos writes them before Terraform runs when auto_generate_files is enabled, or when you run atmos terraform generate files.
You can generate HCL, JSON, YAML, Markdown, or any text file. Backend and provider generation remain common built-in workflows, but generate covers custom auxiliary files too.
- Stack Config (YAML)
- Generated provider.tf
Define generated files declaratively in YAML. String values are treated as Go templates, so stack variables can be rendered into the generated file.
Atmos generates this file before Terraform runs.
Hooks → Hooks
- Terragrunt
- Atmos
Terragrunt supports hooks inside terragrunt.hcl using before_hook, after_hook, and error_hook blocks. Hooks run commands around selected Terraform operations.
Atmos supports lifecycle hooks in stack configuration. Hooks can run before or after Terraform init, plan, apply, and deploy. Atmos also includes native hook kinds for common workflows: infracost for cost estimates, trivy, checkov, and kics for security and policy scanning, plus command for custom scripts.
Remote State Configuration
- Terragrunt
- Atmos
Terragrunt configures remote state in the root terragrunt.hcl using a remote_state block and can create the configured backend resources when they do not exist. The path_relative_to_include() function dynamically generates state keys based on directory structure. Child configurations inherit this through include blocks.
Atmos centralizes backend configuration in YAML and supports automatic backend provisioning with provision.backend. The backend: block describes where state lives, and provision.backend.enabled tells Atmos to create that backend if it does not exist.
Before Terraform runs, Atmos checks whether the backend exists, provisions it if needed, and then continues with terraform init.
Locals → Locals
- Terragrunt
- Atmos
Terragrunt uses locals blocks for computed values and string interpolation. You define local variables with HCL syntax and reference them using local.variable_name. These are scoped to the current file and its includes.
Atmos supports locals for file-scoped computed values and vars for values passed into components. Use locals to reduce repetition or build derived values, then reference them with .locals.* in vars, settings, env, and other templated sections.
Atmos locals are scoped to the file where they are defined. Use vars when you need inherited values across imports, and use locals when you need temporary computed values inside one stack file.
run_cmd → YAML Functions
- Terragrunt
- Atmos
Terragrunt's run_cmd() function executes shell commands and captures their output. You pass the command and arguments as separate strings, and the result can be assigned to a local variable.
Atmos provides YAML functions (like !exec) as the preferred way to run commands or fetch dynamic values. YAML functions are validated at parse time, produce readable configurations, and integrate naturally with YAML syntax.
Atmos also supports Go templates ({{ exec "..." }}), but we recommend YAML functions because:
- Validation: YAML functions are validated at parse time; templates can only be validated after generation
- Readability: Templates turn YAML into string soup that's hard to read and debug
- Tooling: YAML functions work with standard YAML tooling; templates break syntax highlighting and linting
Use templates only as an escape hatch when YAML functions don't cover your use case.
extra_arguments → Component Settings
- Terragrunt
- Atmos
Terragrunt's extra_arguments block lets you append additional CLI arguments to Terraform commands. You specify which commands (plan, apply, etc.) receive the extra arguments and what those arguments should be.
Atmos uses the settings.terraform.args section to pass additional arguments to Terraform. These arguments are appended to all Terraform commands for that component and can be defined at multiple levels with inheritance.
Units and Stacks
Terragrunt recently introduced formal Units and Stacks concepts (GA in v0.78.0, May 2025). Here's how they map to Atmos:
- Terragrunt
- Atmos
In Terragrunt terminology:
-
Unit: A directory containing a
terragrunt.hclfile—a single instance of infrastructure with its own state. Each unit represents one deployment of a Terraform module. -
Stack: A collection of units that can be managed together. Terragrunt supports both implicit stacks (directory-based) and explicit stacks (defined in
terragrunt.stack.hclfiles).
Atmos has always had these concepts, just with different names:
-
Unit → Component Instance: In Atmos, when you define a component in a stack's
components.terraformsection, that's a unit—a single deployable instance with its own state. -
Stack → Stack File: An Atmos stack file (e.g.,
prod-us-east-1.yaml) is exactly what Terragrunt now calls a stack—a collection of component instances managed together.
The key difference: Atmos has used YAML for this since day one, while Terragrunt's terragrunt.stack.hcl is a newer HCL-based approach to the same problem.
| Terragrunt Concept | Atmos Equivalent | Notes |
|---|---|---|
Unit (terragrunt.hcl) | Component instance in components.terraform | Same concept: single deployable with own state |
| Implicit Stack (directory) | Stack file | Atmos uses explicit YAML files, not directories |
Explicit Stack (terragrunt.stack.hcl) | Stack file (.yaml) | Both define collections of units/components |
unit {} block | Component entry under components.terraform | Atmos uses YAML; Terragrunt uses HCL |
values = {} | vars: | Both pass variables to the underlying module |
Terragrunt evolved from a directory-per-unit model and later added explicit stack support. Atmos was designed stack-first—every deployment is defined in a stack file, making the relationship between components explicit and queryable from day one.
Function Mapping
Terragrunt exposes HCL functions for path discovery, environment lookup, command execution, dependency wiring, and file reading. Atmos supports the same workflows, but many of them move from inline functions to explicit YAML configuration, YAML functions, or stack templating. The table below audits the functions in the Terragrunt function reference.
Path and Directory Functions
| Terragrunt Function | Atmos Equivalent | Notes |
|---|---|---|
| OpenTofu/Terraform built-ins | Go templates with Sprig/Gomplate, or YAML functions | Atmos does not expose Terraform's HCL function set directly. Use YAML functions for data access and templates for string, path, list, map, and semver helpers. |
find_in_parent_folders() | import: or !include | Atmos uses explicit imports and includes instead of walking parent directories. |
path_relative_to_include() | Explicit backend.key or templates | Atmos does not derive state keys from include paths. Configure state keys directly from stack/component context. |
path_relative_from_include() | Not usually needed | Atmos imports, component base paths, and source provisioning use configured paths instead of include-relative module paths. |
get_repo_root() | !repo-root | YAML function returns repo root path |
get_path_from_repo_root() | No direct scalar function | Usually not needed; use configured stack/component paths, or combine !repo-root with templates when an absolute repo path is required. |
get_path_to_repo_root() | No direct scalar function | Use !repo-root for the absolute root. Atmos generally avoids relative path hops back to repo root. |
get_terragrunt_dir() | Manifest-relative paths, component base paths | ./ and ../ in !include resolve relative to the manifest file. Component paths come from components.terraform.base_path plus the component name. |
get_working_dir() | !cwd | YAML function returns the directory where Atmos is executed. |
get_parent_terragrunt_dir() | import: | Explicit imports replace parent-config discovery. |
get_original_terragrunt_dir() | !cwd | Atmos is not directory-per-unit; use the command working directory when you need the invocation path. |
Environment and Platform Functions
| Terragrunt Function | Atmos Equivalent | Notes |
|---|---|---|
get_env("VAR", "default") | !env VAR, default | YAML function for environment variables |
get_platform() | No native equivalent | Sprig and Gomplate can read environment variables, but do not expose Go runtime.GOOS/runtime.GOARCH. Use !exec if needed. |
get_aws_account_id() | !aws.account_id | YAML function backed by AWS STS |
get_aws_account_alias() | !exec | No dedicated YAML function; run an AWS CLI command |
get_aws_caller_identity_arn() | !aws.caller_identity_arn | YAML function backed by AWS STS |
get_aws_caller_identity_user_id() | !aws.caller_identity_user_id | YAML function backed by AWS STS |
Terraform Command Helpers
| Terragrunt Function | Atmos Equivalent | Notes |
|---|---|---|
get_terraform_commands_that_need_vars() | Built in | Atmos generates and passes component varfiles automatically for Terraform commands that need them. |
get_terraform_commands_that_need_input() | settings.terraform.args | Configure -input=false or related flags explicitly. |
get_terraform_commands_that_need_locking() | settings.terraform.args | Configure lock flags explicitly when needed. |
get_terraform_commands_that_need_parallelism() | settings.terraform.args | Configure -parallelism explicitly when needed. |
get_terraform_command() | No direct function | Atmos receives the Terraform subcommand from atmos terraform <command>. Use hooks or custom commands when behavior must vary by operation. |
get_terraform_cli_args() | settings.terraform.args, env, or pass-through args | Use component settings for durable args, TF_CLI_ARGS* env vars for Terraform-native behavior, or -- for one-off pass-through args. |
get_default_retryable_errors() | retry.conditions | Atmos has component retry configuration instead of a helper returning default regexes. |
Command Execution
| Terragrunt Function | Atmos Equivalent | Notes |
|---|---|---|
run_cmd("cmd", "arg1", ...) | !exec | !exec cmd arg1 executes shell commands in YAML functions. |
run_cmd("--terragrunt-quiet", ...) | No direct flag | Use Atmos secret masking and avoid printing sensitive command output. |
run_cmd("--terragrunt-global-cache", ...) | No direct flag | Atmos does not expose a command-output cache control for !exec. |
run_cmd("--terragrunt-no-cache", ...) | Default !exec behavior | !exec runs when functions are processed; there is no Terragrunt-style cache toggle. |
Configuration Reading
| Terragrunt Function | Atmos Equivalent | Notes |
|---|---|---|
deep_merge() | Stack imports and inheritance | Atmos deep-merges imported YAML configuration by design. Use Sprig/Gomplate template merge helpers only when inline expression merging is unavoidable. |
read_terragrunt_config() | import: | Import reusable Atmos stack YAML instead of reading HCL into a local value. |
read_tfvars_file() | !include | !include can load .tfvars and .tfvars.json into YAML values. |
sops_decrypt_file() | !exec or stores | No native SOPS YAML function. Use !exec sops ... for local encrypted files, or move secrets to a configured store and read with !store/!store.get. |
get_terragrunt_source_cli_flag() | No direct equivalent | Atmos source provisioning uses source.uri and source.version in stack config. Use !env for local override patterns if you need them. |
State and Outputs
| Terragrunt Function | Atmos Equivalent | Notes |
|---|---|---|
dependency.X.outputs.Y | !terraform.output | !terraform.output component.output_name |
| N/A | !terraform.state | Read arbitrary state attributes |
Change Tracking and Constraints
| Terragrunt Function | Atmos Equivalent | Notes |
|---|---|---|
mark_as_read() | dependencies.components with kind: file | Declare explicit file dependencies so describe affected can track changes. |
mark_glob_as_read() | dependencies.components with kind: folder | Declare folder dependencies instead of imperatively marking glob reads. |
constraint_check() | Sprig semverCompare or tool dependency constraints | Use semverCompare in templates for conditional config, or Atmos toolchain dependency constraints for tool versions. |
Atmos offers two ways to access dynamic values:
- YAML Functions (
!exec,!env,!terraform.output) — Preferred. Validated at parse time, readable, works with YAML tooling. - Go Templates (
{{ env "VAR" }},{{ semverCompare ">=2.0.0" .vars.version }}) — Escape hatch. Use when YAML functions don't cover your use case.
See YAML Functions for the complete reference.
CLI Command Comparison
- Terragrunt
- Atmos
Terragrunt commands are directory-based—you cd into a component's directory and run commands there. For multi-component operations, run-all traverses the directory tree and executes in dependency order.
# Plan a single component
cd prod/us-east-1/vpc
terragrunt plan
# Apply a single component
cd prod/us-east-1/vpc
terragrunt apply
# Plan all components
terragrunt run-all plan
# Apply all components
terragrunt run-all apply
# Show outputs
terragrunt output
Atmos commands run from anywhere within a configured Atmos repository—you never need to cd anywhere. Just specify the component and stack, and Atmos finds everything automatically. This makes scripts and CI/CD pipelines simpler and eliminates directory management entirely.
# Plan a single component (from repo root)
atmos terraform plan vpc -s prod-us-east-1
# Apply a single component
atmos terraform apply vpc -s prod-us-east-1
# Plan ALL components in ALL stacks
atmos terraform plan --all
# Apply ALL components in ALL stacks
atmos terraform apply --all
# Show outputs
atmos terraform output vpc -s prod-us-east-1
# List all stacks
atmos list stacks
# Describe a component
atmos describe component vpc -s prod-us-east-1
GitOps-native: Atmos goes beyond simple "run all" with intelligent change detection:
# See what changed between commits (compares current branch to main)
atmos describe affected
# Plan ONLY components affected by changes in current branch
atmos terraform plan --affected
# Apply ONLY affected components
atmos terraform apply --affected
# Compare against a specific branch or commit
atmos describe affected --ref refs/heads/feature-branch
atmos describe affected --sha abc123def
# Include dependent components (if vpc changed, also plan eks that depends on it)
atmos describe affected --include-dependents=true
This is purpose-built for CI/CD: instead of planning everything on every PR, Atmos analyzes Git changes to determine exactly which components and stacks are affected—including changes to stack configs, component code, and even local Terraform modules.
Migration Steps
Step 1: Convert terragrunt.hcl to Stack YAML
- Before (Terragrunt)
- After (Atmos)
Each Terragrunt directory has its own terragrunt.hcl with include paths, source references, and inputs. The configuration is scattered across the directory tree with implicit relationships based on folder hierarchy.
The Atmos stack file consolidates all configuration in one place. Imports bring in shared defaults, vars set environment-level values, and components define what to deploy. Each component points to a local Terraform module.
Step 2: Move Terraform Root Modules
In Terraform, a root module is the top-level directory where you run terraform plan and terraform apply. It has its own state file. Child modules are reusable building blocks called from root modules—they don't have their own state.
In Atmos terminology, root modules are called components. Each component is a self-contained Terraform configuration that gets deployed independently with its own state.
- Before (Terragrunt)
- After (Atmos)
Terragrunt typically references root modules from a modules/ directory (or pulls from remote sources). These are standard Terraform root modules that work independently.
modules/
├── vpc/ # Root module (has state)
│ ├── main.tf
│ └── variables.tf
└── eks/ # Root module (has state)
├── main.tf
└── variables.tf
Atmos expects root modules (components) in components/terraform/. The modules themselves are unchanged—just move or rename the directory. Your Terraform code remains pure and portable.
components/terraform/
├── vpc/ # Component = root module
│ ├── main.tf
│ └── variables.tf
└── eks/ # Component = root module
├── main.tf
└── variables.tf
Simply rename modules/ to components/terraform/.
Step 3: Update Backend Configuration
- Before (Terragrunt)
- After (Atmos)
Terragrunt manages state backend configuration in the root terragrunt.hcl. The path_relative_to_include() function generates unique state keys based on the directory structure, ensuring each component has its own state file.
Atmos defines backend settings in a shared defaults file. All stacks import this file and automatically get consistent backend configuration. State keys are generated from stack and component names, with optional per-component overrides.
Component-specific key prefixes:
Migration Checklist
- Install Atmos CLI (Installation Guide)
- Create
atmos.yamlconfiguration - Move Terraform root modules to
components/terraform/ - Convert
terragrunt.hclfiles to stack YAML - Extract common config to
_defaults/ - Convert
dependencyblocks to remote state - Update backend configuration
- Test with
atmos terraform plan - Update CI/CD pipelines
- Train team on new commands
Stack Naming for Migrations
Every Atmos command requires a stack name—whether you're running atmos terraform plan -s <stack>, listing stacks with atmos list stacks, or referencing dependencies. You need to define how Atmos determines these names.
Additionally, if you want Atmos to automatically determine Terraform workspaces, those workspace names should follow a consistent convention that Atmos can compute.
You have two options:
Option 1: Use name_template (Recommended for Consistent Patterns)
If you have consistent context variables across all your stacks, configure name_template in atmos.yaml to programmatically compute stack names:
This works well when:
- You have consistent
vars(likeenvironment,stage,tenant) across all stacks - You want programmatic, convention-based naming
- Your Terraform workspaces should follow the same naming pattern
Option 2: Use Explicit name Field (For Inconsistent or Legacy Naming)
If your infrastructure doesn't follow a strict naming convention, use the name field in each stack manifest to explicitly specify the stack name:
This is the right choice when:
- Your stacks don't have consistent context variables
- You're migrating infrastructure from multiple sources with different naming conventions
- Workspace names are ad-hoc or don't follow a pattern you can express as a template
The name field takes precedence over name_template, so you can use both approaches—template for most stacks, explicit names for exceptions.
For complete documentation on stack naming, see Stack Names.
Why Migrate?
Advantages of Atmos
- Clear separation of code and config - YAML for configuration, native Terraform for code. Components (code) and stacks (config) live in different directories—no "Terraform-like but not Terraform" confusion
- Components are pure Terraform - Your modules work with or without Atmos, no vendor lock-in
- YAML is universal - Every language and tool can parse it; no HCL knowledge needed for configuration
- Deep merge semantics - More powerful than
includeblocks - Schema validation - JSON Schema + OPA policies for configuration validation
- Multi-tool orchestration - Not just Terraform (Helmfile, Packer, etc.)
- Active development - Regular releases, responsive community
When to Stay with Terragrunt
- It's working for you - If your team knows Terragrunt well and has no pain points, there's no reason to change
- Strong HCL preference - If your team prefers HCL over YAML and wants configuration in the same language as Terraform code
- Heavy dynamic generation - If you rely extensively on
generateblocks to create arbitrary Terraform files dynamically, Terragrunt's full templating power may be necessary
Get Help
Migrating a large codebase? We're here to help:
- Slack Community - Ask migration questions
- Office Hours - Live support for complex migrations
- GitHub Discussions - Share your migration story
Next Steps
Now that you understand the migration path:
- Learn YAML in Atmos - YAML is more powerful than you might think. Learn how Atmos uses deep merging, scope, and inheritance
- Explore YAML Functions - YAML functions like
!terraform.output,!env, and!execare first-class YAML features (technically explicit tags) that give your configuration superpowers - Try the Quick Start - Get hands-on with Atmos
- Read Core Concepts - Understand Atmos deeply
- Explore Stack Configuration - Advanced YAML features