TF Associate 003 — IaC Concepts, Terraform's Purpose, and the Execution Graph — objectives 1 and 2, and the last two on the arc
The two objectives that read like preamble are the ones whose wrong answers come from the tools next door.
TF Associate 003 — IaC Concepts, Terraform's Purpose, and the Execution Graph
Section IFrame
Seven cert lessons on this arc have opened seven objectives. State, backends, the core workflow, modules, providers, HCP Terraform, testing and validation, state manipulation, sensitive values. All the machinery.
Two objectives were skipped every time, and they sit at the top of the blueprint: understand infrastructure as code concepts, and understand the purpose of Terraform against other IaC tools. They read like the throat-clearing before a course starts.
They are not, on the exam. Objectives 1 and 2 carry question weight, and the questions are built to be missable by a candidate who can write a module and has never had to say what category of tool Terraform belongs to. The wrong answers on those questions are drawn from the tools next door: Ansible, Chef, Packer, Docker, CloudFormation, Pulumi. A candidate who has only ever used Terraform has no vocabulary to separate them.
This lesson closes both. Blueprint coverage after it stands at nine objectives of nine.
Section IIObjective 1: What Infrastructure as Code Actually Claims
The claim in one sentence
Infrastructure as code means the infrastructure is defined in files, the files are the source of truth, and changes reach the world by changing the files.
The consequence that matters is the second clause. Nothing prevents an engineer from opening the AWS console and clicking. What IaC claims is that when they do, the files are now wrong, and being wrong is detectable. The code is the record. A console change is not a fifth way of doing the work; it is drift against the record.
Brikman lists five benefits and they are worth having in the order he gives them: self-service, speed and safety, documentation, version control, validation and reuse (Ch. 1, pp. 49-50). Documentation is the one candidates undervalue and the one exam writers like, because the configuration is not a description of the system that can rot separately from the system. It is the system's definition.
Four categories of tool, and the word that hides them
The exam wants a candidate who can place tools in categories. Brikman gives five; four of them appear in questions.
| Category | What it produces | Examples |
|---|---|---|
| Ad hoc scripts | Whatever the author wrote, in whatever order | Bash, Python, PowerShell |
| Configuration management | A configured server, from an existing server | Ansible, Chef, Puppet, SaltStack |
| Server templating | An image, built once, deployed many times | Packer, Docker, Vagrant |
| Provisioning | Infrastructure itself, from the cloud API | Terraform, CloudFormation, Pulumi, OpenTofu |
Say the distinction plainly: configuration management configures a machine that exists; provisioning creates the machine. Ansible installs nginx on a server. Terraform creates the server for Ansible to configure. Packer bakes an image so that neither has to install nginx at boot.
The category boundary is not a wall, and the exam does not pretend it is. Ansible can create EC2 instances; Terraform can run a provisioner that installs a package. The question to answer is what the tool is for, and the tell is what the tool does when it is pointed at a machine that already looks right. Configuration management converges it. Provisioning compares it to a recorded state and reports the difference.
Brikman is direct about the practical pairing, and it is the answer most likely to be the correct one on a scenario question: use a provisioning tool for the infrastructure and a server templating tool for the images, and reach for configuration management only where the fleet is mutable by design (Ch. 1, pp. 33-34 and pp. 46-47).
Mutable and immutable
The distinction runs underneath every category above. Mutable infrastructure means a server is upgraded in place: the machine that ran version 3 now runs version 4, and its history is whatever happened to it. Immutable means the machine that ran version 3 is destroyed and a machine built for version 4 replaces it.
Configuration management is native to the mutable model. Server templating plus provisioning is native to the immutable one. Brikman names the failure mode of the mutable model as configuration drift, where the fleet diverges because each server accumulated a slightly different history of upgrades (Ch. 1, p. 56).
Two things to carry into the exam room. Terraform's default replacement behavior is immutable, which is why the day's Ops lesson had to work so hard to keep a service up during a replacement. And immutable is a claim about servers rather than about state files; the state file is mutable by definition, and it is the one thing in the system that records history.
Declarative and imperative
An imperative tool is told the steps. A declarative tool is told the result.
Terraform is declarative. The configuration says there are four instances of this shape, and Terraform works out whether that means creating four, creating one more, destroying two, or doing nothing. A Bash script that creates four instances, run twice, creates eight.
The property this buys is idempotence: applying the same configuration to the same world twice produces the world once. This is exactly the claim the day's Dev lesson turns into a test assertion, and it is worth noticing that the property has to be tested rather than assumed, because a configuration can be written that never settles.
Section IIIObjective 2: The Purpose of Terraform
What Terraform is for
Terraform provisions infrastructure across many providers from one declarative language, and records what it created in a state file so that the next run knows what already exists.
The state file is the answer to more exam questions than any other single fact in this objective. It is what makes the tool declarative in practice. Without it, Terraform would have to ask the cloud what exists and guess which of those things it owns.
Brikman's description of the mechanism is compact and worth reciting: Terraform reads the configuration, reads the state, queries the providers for real-world status, computes a diff, and executes the diff through provider API calls (Ch. 1, pp. 51-52). Five steps. The plan is step four made visible.
Terraform against the neighbours
| Tool | Category | Scope | Language | State |
|---|---|---|---|---|
| Terraform | Provisioning | Multi-cloud, any provider | HCL, declarative | Explicit state file |
| CloudFormation | Provisioning | AWS only | YAML/JSON, declarative | Managed by AWS, invisible |
| ARM / Bicep | Provisioning | Azure only | JSON / Bicep DSL | Managed by Azure |
| Pulumi | Provisioning | Multi-cloud | General-purpose languages | Explicit state |
| Ansible | Config management | Any host | YAML, procedural-ish | Stateless, converges |
| Chef / Puppet | Config management | Any host | Ruby DSL | Agent-reported |
Two rows carry the exam weight.
CloudFormation is the cloud-native comparison, and the distinction that matters is not the language. It is that AWS holds the state and Terraform hands it to you. AWS holding it means no bucket to configure and no lock table to create. It also means no terraform state mv, no import into a file you can inspect, and no way to read what the tool believes without asking AWS. The 08-03 lesson on state manipulation only exists because Terraform's state is a file the operator can reach.
Ansible is the category comparison, and the tell is idempotence versus convergence. Ansible modules are written to be idempotent, and Ansible has no record of what it did last time. Point it at a fresh server and it configures it; point it at a configured one and it changes nothing. Terraform knows what it made, which is why it can destroy.
Why HCL rather than a programming language
Pulumi's pitch is that infrastructure should be written in TypeScript or Go, where loops, functions, and unit tests come free. The Terraform answer is that a domain-specific language constrains what can be expressed, and a constrained configuration is one a reader can predict and a policy engine can evaluate.
The 08-09 lesson is the practical version of that argument. A Sentinel or Rego rule reads a plan and decides. That works because the plan is a bounded, documented artifact rather than the output of arbitrary program execution.
Objective 2 also expects a candidate to know what HCP Terraform adds on top: remote state with locking, remote runs, a private module registry, policy enforcement, cost estimation, and workspace-level access control. The 07-28 and 08-09 lessons cover those in depth. For this objective, knowing the list is enough.
Section IVPro-Depth: The Execution Graph
The Associate objectives stop at Terraform builds a dependency graph. The Professional exam expects more, and the day's Ops lesson makes no sense without it.
The graph is derived from references
Terraform builds a directed acyclic graph where nodes are resources, data sources, providers, and outputs, and edges come from references between them. Write vpc_id = aws_vpc.main.id and the edge is created. No author declares it.
Brikman demonstrates this with a security group and an instance in the first working example, and the demonstration is the point: the dependency is a consequence of using a value, not of announcing an intention (Ch. 2, pp. 107-110). The graph is the program. The configuration is a set of declarations; the graph is what actually runs.
terraform graph prints it in DOT format, which is the exam-answerable command.
What the graph gives you
Order on create: dependencies first. Order on destroy: the graph reversed, dependents first. Parallelism: any two nodes with no path between them are walked concurrently, ten at a time by default, tunable with -parallelism=n.
That default is worth knowing for two reasons. It is a common question, and it is the first thing to lower when a provider starts returning rate-limit errors on a large apply.
depends_on and where it belongs
depends_on adds an edge the references did not create. It is for hidden dependencies: an IAM policy attachment that must land before an instance can call an API, where no attribute of the policy appears in the instance's configuration.
The discipline is to use it rarely. An edge added by hand is an edge that stays after the reason for it is gone, and a graph with hand-added edges serializes work that could have run in parallel. Prefer restructuring the configuration so the reference exists.
Where lifecycle sits in the graph
The day's Ops lesson turns on this. create_before_destroy does not add or remove edges. It inverts the order of the two operations at a single node during a replacement, and Terraform then propagates that inversion to every node upstream in the dependency chain, because a dependent that still points at the old resource cannot be destroyed while the new one is being created.
The asymmetry is the exam-grade detail: the propagation travels toward dependents, never toward dependencies, and a resource with the flag depending on one without it produces a cycle error.
Section VPractice Questions
terraform state list, state mv, state rm, import, and show -json all work against it. CloudFormation's state is held by AWS and cannot be inspected or surgically edited the same way. The tradeoff is that Terraform's state must be stored, locked, and protected, and CloudFormation's does not.terraform plan immediately afterward shows a change. What does this indicate?ignore_changes. A declarative tool should produce an empty plan against a world it just built.terraform graph, output in DOT format. Default parallelism is 10 concurrent node operations, adjustable with -parallelism=n. Lowering it is the standard response to provider rate-limiting on a large apply.depends_on on the instance, naming the attachment. The cost is a hand-maintained edge: it survives the reason for its existence, and it serializes work the graph would otherwise parallelize. Restructuring so a real reference exists is better where it is possible.Section VIClosing
Objectives 1 and 2 are not warm-up. They are the vocabulary the rest of the blueprint assumes, and a candidate who cannot place Ansible, Packer, and CloudFormation on a category map will lose points on questions that have nothing to do with HCL.
Learn four categories and the one-line test that separates them. Learn the five-step mechanism: configuration, state, real-world query, diff, API calls. Learn that the graph comes from references, that destroy walks it backwards, that parallelism defaults to ten, and that create_before_destroy inverts an order at a node and propagates toward dependents.
Then read the day's Ops lesson again with the graph in mind, and notice that every rule in it follows from the shape of the graph rather than from Terraform's preferences.
Nine objectives of nine are now open on this arc. The work ahead is depth, not coverage.
Examine well.
Cross-ReferencesRelated
- Prior arc: [[Atrium/Archmagus-Stack/Cert-Prep/HashiCorp/2026-08-09-terraform-associate-003-sensitive-variables-secrets-in-state-and-hcp-terraform-policy-enforcement-objectives-4-8-and-9/lesson|TF Associate 003 — Sensitive Variables, Secrets in State, and HCP Terraform Policy Enforcement]]
- Domain hub: [[Cross-References/Archmagus-Stack]]
- Grounding tome: [[Atrium/Archmagus-Stack/09-Tomes/01-Earth-DevOps/Brikman Y. Terraform. Up and Running. Writing...as Code 3ed 2022|Terraform: Up and Running, 3ed]] (Ch. 1, Why Terraform, pp. 33-56)
- Paired Ops lesson: [[Atrium/Archmagus-Stack/01-Earth-DevOps/Synthesis-Lessons/2026-08-12-terraform-resource-lifecycle-on-aws-create-before-destroy-ignore-changes-replace-triggered-by-and-zero-downtime-asg-replacement/lesson|Terraform's Resource Lifecycle on AWS]]
- Paired Dev lesson: [[Atrium/Archmagus-Stack/Polyglot-Dev/Go/2026-08-12-terratest-under-change-http-polling-through-a-zero-downtime-deploy-test-stages-and-the-empty-plan-idempotence-assertion/lesson|Terratest Under Change]]
Filed 2026-08-12 · Fajr trio #87 · sprint day 21 · TF track
Paired: 01-Earth-DevOps/Synthesis-Lessons/2026-08-12-terraform-resource-lifecycle-on-aws/ · Polyglot-Dev/Go/2026-08-12-terratest-under-change/