Domain 4 of 8

Terraform configuration

Domain · 22% of the TA-004 exam

A configuration declares desired state, and references wire it into a graph

Terraform configuration is the single largest domain on TA-004, covering eight subtopics, more than any other domain, and it is where you actually write HCL (HashiCorp Configuration Language). The language is declarative: you describe the end state you want block by block, and Terraform works out how to reach it. The unit of that description is the block: a resource or data block declares infrastructure, a variable or output block declares an interface, and a locals block names reusable values. Blocks are wired together by references such as aws_vpc.main.id, var.region, or module.network.subnet_id, and each reference does two jobs at once. It carries a value, and it declares an ordering, because Terraform reads references to build a dependency graph rather than running the file from top to bottom. Hold onto that one model and most of the domain follows: everything here either declares a block, produces or consumes a value, or shapes how those values flow.

The domain unfolds in eight moves, from blocks to guardrails

The eight subtopics build on that model in the order they are numbered. First, resource and data blocks separate the two core block types: a resource block owns an object's full create, update, and destroy lifecycle, while a data block only reads an existing object. Referencing resource attributes then covers how to name a value across blocks, with a fixed prefix per kind (var., local., data., module.) and a bracket selector, [index] for a counted resource or [key] for a keyed one, to reach a single instance. Variables and outputs defines a module's public interface, the inputs it accepts and the results it returns, plus the fixed precedence that resolves a variable's final value. Complex types describes the shapes a value can hold, splitting collection types (list, set, map) from structural types (object, tuple). Expressions and functions shows how to compute a value instead of hard-coding it, through built-in functions, conditionals, for expressions, the splat operator, dynamic blocks, and string templates. Resource dependencies returns to ordering, contrasting the implicit dependencies that references create with the explicit depends_on escape hatch and the lifecycle settings that tune replacement. Custom condition validation adds assertions that catch a bad value early, from variable validation to pre- and postconditions to check blocks. Managing sensitive data closes the domain: sensitive only redacts display, ephemeral values and write-only arguments actually keep a secret out of state, and Vault moves the secret out of the configuration though its fetched value still lands in state.

Prefer the declarative, native construct; the last resort is rarely the answer

When two answers both produce working infrastructure, this domain rewards the one that stays declarative and lets Terraform's own machinery do the work. Prefer an implicit reference over depends_on, for_each over count when instances need stable identity, a built-in function or expression over a provisioner, and a purpose-built secret mechanism over trusting sensitive to protect state. The recurring tell is the phrase last resort: HashiCorp's docs apply it to provisioners and local-exec, and an option the documentation calls a last resort is almost never the intended choice when a native construct exists. The same instinct explains the domain's sharpest traps: sensitive hides a value from the console yet still writes it to state in plain text, and prevent_destroy errors out a destroy plan rather than silently skipping the resource.

The eight configuration concerns and where each is covered

Configuration concernWhat it declares or doesReach for it whenDrill into
Blocks`resource` owns an object's lifecycle; `data` only reads oneYou declare a piece of infrastructure or look one upResource and data blocks
ReferencesName a value across blocks by prefix, and address one instance by index or keyOne block needs a value another block producedReferencing resource attributes
Variables and outputsA module's inputs and results, resolved by a fixed precedenceYou parameterize a module or expose a resultVariables and outputs
Complex typesCollection types (list, set, map) versus structural types (object, tuple)A value holds many items or a fixed-shape recordComplex types
Expressions and functionsCompute a value with functions, conditionals, for, splat, dynamic blocks, and templatesA value must adapt to its inputs rather than be hard-codedExpressions and functions
DependenciesImplicit references order the graph; `depends_on` and `lifecycle` tune itWork must run in a set order, or a replacement needs controlResource dependencies
ValidationAssertions: variable validation, pre/postconditions, and check blocksYou catch a bad value or a broken assumption earlyCustom condition validation
Sensitive data`sensitive` redacts display; ephemeral and write-only keep secrets out of state; Vault moves them out of configA secret must not leak into logs or stateManaging sensitive data

Subtopics in this domain