Terraform

Terragrunt Primer: Practical Guidance for Running Terraform DRY

2026-04-19
NicheeLab Editorial Team

Terragrunt is a lightweight wrapper around Terraform aimed at keeping module reuse, shared remote state configuration, and per-environment differences DRY.

For exam prep, the top priority is a solid understanding of Terraform's official features (modules, backends, state management, workspaces, CLI behavior). Terragrunt is useful in real work, but the exams focus on how Terraform itself behaves.

Where Terragrunt Fits and How It Relates to the Exam Scope

Terragrunt is a helper that invokes the Terraform CLI. From an HCL-based terragrunt.hcl file it fetches modules, injects input variables, and applies shared configuration. Core capabilities such as state management, plan, and apply remain Terraform's responsibility.

The Terraform Associate/Pro exams assume understanding of official features: backends, state files, module composition, workspaces, and detailed CLI behavior. Terragrunt-specific syntax and subcommands are unlikely to appear directly; even when they do, the question can be answered by reasoning from Terraform's principles.

  • Focus of DRY: sharing state and provider configuration
  • Terraform's source of truth: .tf / .tf.json and state (Terragrunt does not alter this)
  • For the exam, focus your review on Terraform backends, locking, and dependency resolution

Terraform vs Terragrunt: A Quick Comparison of Responsibilities

Separating the two responsibilities keeps your design stable. Terraform is the execution engine for infrastructure declaration and state management. Terragrunt is the orchestration and sharing layer that invokes it.

Here is a side-by-side of the points that tend to confuse teams in practice.

  • The source of truth for state is the Terraform backend (S3, GCS, AzureRM, etc.)
  • Dependency ordering and injecting shared configuration are organized by Terragrunt
  • Plan output and the side effects of apply are Terraform's responsibility
ItemTerraformTerragrunt
RoleEvaluate declarations, plan and apply, manage stateOrchestrate Terraform runs and keep them DRY (shared config, dependency order)
Unit of configuration.tf / .tfvars (per module)terragrunt.hcl (per module invocation)
Backend / lockingManaged via official backend featuresStandardized and injected into each module (does not provide locking itself)
DependenciesModules connect indirectly through outputs and inputsdependency references and explicit execution ordering (invocation order)
CLIterraform init/plan/apply, etc.terragrunt run-all / plan / apply (invokes terraform under the hood)
Managing differencesVariables, workspaces, and file splittingOrganize per-environment differences with locals, include, and a directory hierarchy

Directory Strategy and Expressing Dependencies

With Terragrunt, slicing the hierarchy by environment x service x layer (networking / data / app) makes it easy to balance sharing and differences. Put a shared terragrunt.hcl at the upper level and describe only the minimum required differences below.

Design dependencies so execution flows in an order such as networking → data → app. Keep in mind that the source of truth for state lives in each module's backend, and Terragrunt is simply invoking terraform commands in that order.

  • Place shared locals and remote_state at the top, and put inputs and source specifications below
  • Split dependencies at a not-too-tight granularity (such as network boundaries)
  • run-all is convenient, but narrow the target when applying destructive changes

Example of an environment hierarchy and its dependencies

live/
  ├─ prod/
  │   ├─ networking/
  │   │   └─ vpc/             (depends: none)
  │   ├─ data/
  │   │   └─ rds/             (depends: prod/networking/vpc)
  │   └─ app/
  │       ├─ ecs/             (depends: prod/networking/vpc, prod/data/rds)
  │       └─ alb/             (depends: prod/networking/vpc)
  └─ dev/
      ├─ networking/
      │   └─ vpc/
      └─ app/
          └─ ecs/

関係:
[vpc] --> [rds] --> [ecs]
[vpc] --> [alb]

Basic terragrunt.hcl Patterns (Sharing and Differences)

The baseline is to define remote state and provider configuration in a shared file and to write only module sources and inputs at the lower level. The Terraform backend settings are ultimately propagated into each module's terraform init.

Below is a minimal pattern that shares an S3 backend and injects module variables per environment.

  • Share backend configuration via remote_state
  • Centralize module references with terraform.source
  • Inject environment-specific values via inputs, and unify naming conventions with locals

Examples of the shared terragrunt.hcl and lower-level modules

# live/terragrunt.hcl(共通)
locals {
  env = basename(get_terragrunt_dir())  # prod / dev など
  name_prefix = "acme-${local.env}"
}

remote_state {
  backend = "s3"
  config = {
    bucket         = "acme-tfstate-${local.env}"
    key            = "${path_relative_to_include()}/terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "acme-tf-locks"
    encrypt        = true
  }
}

# live/prod/networking/vpc/terragrunt.hcl(下位)
include "root" {
  path = find_in_parent_folders()
}

terraform {
  source = "git::https://example.com/iac-modules.git//aws/vpc?ref=v1.2.3"
}

inputs = {
  name        = "${local.name_prefix}-vpc"
  cidr_block  = "10.0.0.0/16"
}

# live/prod/app/ecs/terragrunt.hcl(依存の参照例)
dependency "vpc" {
  config_path = "../../networking/vpc"
}

terraform {
  source = "git::https://example.com/iac-modules.git//aws/ecs?ref=v1.2.3"
}

inputs = {
  cluster_name = "${local.name_prefix}-ecs"
  vpc_id       = dependency.vpc.outputs.vpc_id
}

Operational Best Practices and Pitfalls

In real-world operations, the top priority is not breaking Terraform's principles. Guarantee state authority, locking, and consistency between plan and apply first, then layer Terragrunt's sharing and ordering on top.

When a change has a large blast radius, avoid applying everything at once with run-all and instead validate in order, starting from directories with the smallest impact. In CI/CD, be strict about passing environment variables, archiving plan output, and designing approval gates.

  • Leave backend and locking to Terraform's own features (such as DynamoDB locking)
  • Pin provider versions and roll out upgrades in small steps
  • Avoid overly deep dependencies (steer clear of cycles and giant graphs)
  • Split plans into human-reviewable units and run apply with a least-privilege identity
  • Always nail down the procedure in a test environment before running state operations (mv, rm, import)

Exam Prep Notes (Focus Points for the Pro Exam)

The exam tests core Terraform skills rather than Terragrunt-specific syntax. In particular, prioritize backend initialization, state migration, workspaces, module design, and interpreting differences (reading plan output).

Even when you share configuration with Terragrunt, remember that fundamentally terraform init/plan/apply runs in each module's working directory; keeping this in mind helps you reason correctly about exam questions.

  • Understand the procedure for changing backends (such as init -migrate-state)
  • Safe ordering for applying state mv / import / rm
  • When to use workspaces vs variable files
  • Conventions for module references (registry / VCS) and pinning versions
  • Assessing risk from plan output (replacement vs update, destructive changes)

Check Your Understanding

Pro

問題 1

A team has standardized the S3 backend configuration with Terragrunt and is sequentially applying multiple directories with run-all. They need to safely detach a resource (state rm) from a particular module's state. From a Terraform Associate Pro perspective, which is the correct response?

  1. Running state rm in any upper-level Terragrunt directory automatically excludes it from every state file beneath it
  2. Move into the target module's working directory and run terraform state rm so the change applies only to the state file referenced by that backend
  3. Manually deleting the tfstate object from the S3 bucket removes the need for terraform state rm
  4. Switching workspaces automatically restricts state rm to the correct state, so it does not matter where you run it

正解: B

State operations are performed against a specific state file via the Terraform CLI. Even when Terragrunt is used for sharing, the source of truth is the state tied to the backend initialized in each module's working directory. Manually deleting the S3 object is risky, and switching workspaces does not guarantee that the right state is targeted.

Frequently Asked Questions

Does Terragrunt change Terraform's backend or locking mechanism?

No. Backend types and locking are Terraform features. Terragrunt's role is to propagate shared configuration into each module's init step, while Terraform itself is responsible for state consistency.

Is it safe to apply all environments at once with run-all?

It can work if dependencies and blast radius are well understood and the plan has been reviewed, but for destructive or far-reaching changes a phased rollout is safer. Especially in production, apply small slices in order, starting from networking and data layers.

Do I need to know Terragrunt for the Terraform exams?

It is unlikely to be tested directly. The exams focus on Terraform's official features (backends, state operations, modules, workspaces, CLI). Even when using Terragrunt, prepare to reason from those Terraform principles.

Check what you learned with practice questions

Practice with certification-focused question sets

無料で問題を解いてみる
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Terraform

HCL Syntax: Terraform's Configuration Language (2026)

HCL2 fundamentals for Terraform — blocks, attributes, expres...

Terraform

Terraform Authoring & Operations Pro: Complete Guide (2026)

Tactics for the Terraform Pro exam — module authoring, works...

Terraform

Terraform Providers: Plugin Management Fundamentals (2026)

Provider mechanics — required_providers, versions, mirrors, ...

Terraform

Terraform Resource Blocks: Declarative Infra Units (2026)

Resource block fundamentals — addresses, references, common ...

Terraform

Terraform Data Sources: Read-Only External Data (2026)

Data source basics — declaration, refresh behavior, dependen...

Browse all Terraform articles (102)
© 2026 NicheeLab All rights reserved.