Terraform & HCL Vocabulary: 30 Terms for Infrastructure as Code

Master Terraform and HCL vocabulary — resource, provider, state, workspace, module, plan/apply, count vs for_each, backend, drift detection, and more for IaC teams.

Infrastructure as Code (IaC) has transformed how teams manage cloud infrastructure — and Terraform, with its HCL (HashiCorp Configuration Language) syntax, is the dominant tool. Whether you are writing Terraform yourself, reviewing pull requests for infrastructure changes, or working alongside a DevOps engineer, this vocabulary will help you follow the conversation and contribute clearly.


HCL Building Blocks

Resource

A resource is the most fundamental element in Terraform. It represents a single infrastructure object — a virtual machine, a database, a DNS record, a storage bucket. Resources are declared with the resource block.

“We need to add a aws_s3_bucket resource for the static assets. Each resource in Terraform maps to one infrastructure object.”

Data Source

A data source (declared with data) lets you fetch information about existing infrastructure that Terraform does not manage. You read it, but do not create or modify it.

“We’re using a data block to look up the existing VPC by tag — we don’t want Terraform to create a new one.”

Variable

A variable (declared with variable) is an input parameter for a Terraform configuration. Variables make configurations reusable across environments.

“The instance size is a variable — pass t3.small for dev and t3.xlarge for production.”

Output

An output (declared with output) exposes values from your Terraform configuration — for example, an IP address or a resource ID — so other configurations or users can consume them.

“We expose the database endpoint as an output so the application team can reference it in their own Terraform config.”

Local

A local (declared with locals) is a computed value you define once and reference multiple times within a configuration. Think of it as a local variable for DRY code.

“We defined a locals block for the common tags so we’re not repeating them in every resource.”


Providers and State

Provider

A provider is a plugin that communicates with a specific cloud or service API — AWS, Google Cloud, Azure, Kubernetes, GitHub. Providers are declared at the top of a configuration and downloaded with terraform init.

“We’re adding the cloudflare provider to manage DNS records — we need to add it to the required_providers block and run terraform init.”

State File

The state file (terraform.tfstate) is a JSON file that tracks the current state of your managed infrastructure. Terraform uses it to determine what changes to make.

“Never edit the state file manually. If it gets corrupted, recovering infrastructure management can be painful.”

Remote State

Remote state stores the state file in a shared backend — S3, Terraform Cloud, GCS — rather than locally. Essential for teams: only one person can hold the state lock at a time.

“We moved to remote state in S3 with DynamoDB locking — no more conflicts when two engineers run terraform apply simultaneously.”

Backend Configuration

The backend defines where the state file is stored and how operations are executed. Configured in a backend block inside terraform { }.

“Our backend is configured to use S3 for state storage and DynamoDB for state locking.”

dependency_lock.hcl

The .terraform.lock.hcl file records the exact versions of providers used in the configuration. It should be committed to version control so all team members use the same provider versions.

“Commit the lock file — it ensures everyone on the team uses the same version of the AWS provider.”


Workspaces and Modules

Workspace

A workspace is an isolated instance of state within a single configuration. Teams use workspaces to manage multiple environments (dev, staging, production) with one codebase.

“We have three Terraform workspaces: dev, staging, and prod. Run terraform workspace select prod before applying production changes.”

Module

A module is a reusable package of Terraform configuration. A root module is the main configuration you apply; child modules are reusable building blocks.

“We built a vpc module that we call from every environment — one definition, used three times.”

Calling a Module

You call a module with a module block, passing input variables. The module encapsulates the resources and exposes outputs.

“We’re calling the rds-cluster module with instance_class = var.db_size — the module handles the rest.”

Creating a Module

When you create a module, you build a folder with its own variables.tf, main.tf, and outputs.tf. The convention keeps inputs, resources, and outputs clearly separated.


Core Terraform Commands

terraform init

terraform init downloads providers, sets up the backend, and prepares the working directory. Always run it after cloning a repo or adding a new provider.

terraform validate

terraform validate checks the configuration for syntax errors and internal consistency — without connecting to any provider.

“Always run terraform validate in CI before running plan — it catches syntax errors instantly.”

terraform fmt

terraform fmt formats HCL code to the canonical style. Running it in CI keeps code formatting consistent across the team.

terraform plan

terraform plan computes and shows what changes Terraform would make if applied. It does not make any changes — it is a dry run.

“Always review the plan output before applying. Look for unexpected destroys — they can cause downtime.”

terraform apply

terraform apply executes the planned changes against real infrastructure. It asks for confirmation unless you pass -auto-approve.

terraform destroy

terraform destroy removes all infrastructure managed by the current configuration. Handle with extreme care in production.

“We ran terraform destroy on the staging environment at the end of the sprint to avoid unnecessary cloud costs.”

terraform import

terraform import brings an existing infrastructure resource under Terraform management by associating it with a resource block.

“The load balancer was created manually. We import-ed it into Terraform so future changes go through code review.”


Advanced Patterns

Drift Detection

Drift occurs when the real state of infrastructure diverges from what the state file records — usually because someone made a manual change outside Terraform. terraform plan reveals drift.

“The plan shows that the security group rule was added manually — that’s drift. We need to either import it or remove it.”

count vs for_each

count creates multiple identical copies of a resource using an integer. for_each creates resources from a map or set, giving each one a stable key. Prefer for_each when elements have meaningful identifiers.

“Use for_each with a map of bucket names rather than count with an index — if you remove a bucket from the middle, for_each only destroys that one; count would destroy and recreate everything after it.”

Dynamic Block

A dynamic block generates repeated nested blocks inside a resource based on a collection — useful when the number of sub-elements is variable.

“We used a dynamic block for the ingress rules so we can pass any number of CIDR ranges as a variable.”

Environment Variables in Terraform

Terraform reads environment variables prefixed with TF_VAR_ as input variables: TF_VAR_region=eu-west-1. This is the standard way to pass secrets and environment-specific values in CI pipelines.

“Set TF_VAR_db_password in GitHub Actions secrets — never put passwords in .tfvars files that get committed.”


Common Terraform Phrases

PhraseMeaning
”Run a plan first”Preview changes before applying them
”There’s drift in the state”Real infrastructure differs from the state file
”The state is locked”Another operation is running — wait for it to finish
”Refactor to a module”Extract reusable config into a separate module
”The resource will be destroyed”Terraform will delete and recreate that resource
”We need to import this”Bring a manually created resource under Terraform management
”Pin the provider version”Specify an exact version in required_providers to avoid surprises