Skip to main content

Terraform DAG Concurrency

· 2 min read
Mikhail Shirkov
Senior Engineer @ NXT:FWD

Atmos Terraform bulk commands now run through a dependency graph, with optional bounded concurrency for plans and deterministic ordering for multi-component runs.

What Changed

  • Routed Terraform --all, --components, and --query through the scheduler-backed Terraform adapter.
  • Built Terraform dependency graphs from dependencies.components first, with legacy settings.depends_on as a fallback.
  • Preserved auth setup, store resolver behavior, YAML function processing, CI hook capture, and per-component output handling on the graph-backed path.
  • Reversed Terraform destroy graph execution so dependents are destroyed before dependencies.
  • Added optional Terraform plan concurrency with --max-concurrency, defaulting to sequential execution.
  • Added plan log controls: --failure-mode, --log-order, --hide=no-changes, and --execution-summary-file.

How to Use It

Run every Terraform component in dependency order:

atmos terraform plan --all -s prod

Run a named subset while preserving dependency edges between selected components:

atmos terraform plan --components vpc,eks/cluster,eks/apps -s prod

Run a query-selected subset:

atmos terraform plan --query '.settings.tier == "network"' -s prod

Destroy in reverse dependency order:

atmos terraform destroy --all -s prod

Enable bounded plan concurrency:

atmos terraform plan --all -s prod --max-concurrency 4

Group each component's logs after it finishes, suppress unchanged plan output, and write a machine-readable execution summary:

atmos terraform plan --all -s prod \
--max-concurrency 4 \
--failure-mode keep-going \
--log-order grouped \
--hide=no-changes \
--execution-summary-file /tmp/atmos-plan-summary.json

Why This Matters

  • Bulk Terraform commands now use one dependency-aware execution path instead of separate routing for each selection mode.
  • Serial runs are deterministic because components are ordered by the graph, not by map iteration.
  • Large projects can speed up plan feedback by running independent components concurrently.
  • Concurrent output remains readable because stdout and stderr are isolated per component.
  • --max-concurrency defaults to 1, preserving existing sequential behavior unless operators opt in.
  • --failure-mode fail-fast remains the default; --failure-mode keep-going lets independent graph branches continue after a failure.
  • Interactive identity selection is rejected when concurrency is greater than 1.
  • Concurrent mutating operations require -auto-approve when enabled.

Get Involved

Try the new graph-backed path on a lower environment first. Feedback and testing reports are welcome, especially for large dependency graphs, query-selected runs, and CI pipelines that plan many components at once.