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_bucketresource 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
datablock 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.smallfor dev andt3.xlargefor 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
localsblock 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
cloudflareprovider to manage DNS records — we need to add it to therequired_providersblock and runterraform 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 applysimultaneously.”
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, andprod. Runterraform workspace select prodbefore 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
vpcmodule 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-clustermodule withinstance_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 validatein CI before runningplan— 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 destroyon 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
planshows 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_eachwith a map of bucket names rather thancountwith an index — if you remove a bucket from the middle,for_eachonly destroys that one;countwould 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
dynamicblock 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_passwordin GitHub Actions secrets — never put passwords in.tfvarsfiles that get committed.”
Common Terraform Phrases
| Phrase | Meaning |
|---|---|
| ”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 |