Skip to main content
Welcome to this concise guide to HashiCorp Configuration Language (HCL) — the primary language used to write Terraform configurations. This article explains what HCL is, why Terraform uses it, and how to read, write, and organize HCL files so your infrastructure-as-code (IaC) is clear, consistent, and maintainable. HCL is a domain-specific, declarative configuration language designed to describe infrastructure in a human-friendly way. It strikes a balance between simplicity and expressiveness so both new users and experienced operators can declare infrastructure intent that Terraform can act on.
A purple presentation slide titled "HashiCorp Configuration Language (HCL)" with the subtitle "Terraform configuration language to describe the infrastructure that Terraform manages." The Terraform logo is visible in the top-right corner.

Declarative nature

Terraform (and HCL) is declarative: you describe the desired state of your infrastructure, not the imperative steps to reach it. Think of it like ordering at a restaurant — you state the final dish you want, and the chef handles the preparation. HCL’s readability makes configurations easier to understand, review, and maintain, improving collaboration across teams.

HCL structure overview

HCL code is composed of blocks. Blocks group related configuration and follow a predictable pattern:
  • A block type (keyword) — e.g., resource, data, provider.
  • Zero or more labels — e.g., resource type and name: "aws_vpc" "vpc".
  • A body in curly braces { ... } containing attributes (arguments) or nested blocks.
HCL supports comments:
  • Single-line: # comment or // comment
  • Multi-line: /* multi-line comment */
Generic HCL block example:

Example (main.tf)

Terraform files use the .tf extension (for example, main.tf). The example below shows data blocks (read-only lookups) and a resource block (declares infrastructure to create/manage).
Notes on the example:
  • data blocks perform lookups of existing information (no additional arguments required in this example).
  • The resource block defines an AWS VPC with the cidr_block attribute and a tags map.
  • Inline comments (prefixed with #) document intent — recommended but optional.

Block anatomy (detailed)

Breakdown of the resource block:
  • resource — block type: declares infrastructure managed by Terraform.
  • "aws_vpc" — resource type: specific provider resource.
  • "vpc" — resource name: a local identifier used to reference this resource in the configuration (e.g., aws_vpc.vpc).
  • { ... } — block body that contains attributes and nested blocks.
  • Inside the block are attributes (arguments) such as cidr_block and the tags map.
To reference this resource elsewhere in your configuration, use aws_vpc.vpc. If you create multiple VPCs, give each resource a unique name (for example, aws_vpc.prod and aws_vpc.test).

Style and conventions

Consistent formatting and naming make HCL easier to read and collaborate on. Below are common conventions used across the Terraform ecosystem: Example alignment style inside a block:
Use blank lines to separate logical groups of arguments within a block to improve readability. Modern editors like Visual Studio Code and the HashiCorp Terraform extension can auto-format and lint HCL to these conventions.
Use terraform fmt or your editor extension to automatically format HCL to standard style.

Best practices and tips

  • Keep variables and outputs well-documented with description fields.
  • Group related resources in modules for reuse and separation of concerns.
  • Avoid committing sensitive secrets directly — use secure variable management or secret backends.
  • Prefer small, focused modules and clear naming to make state management and drift detection easier.
  • Use terraform validate and terraform plan to catch errors before applying changes.

Summary

HCL is a readable, declarative language tailored for Terraform and infrastructure-as-code:
  • Describe the desired state; Terraform determines the steps.
  • Organize configurations into blocks with types, labels, and bodies.
  • Follow conventions: comments, snake_case naming, two-space indentation, and aligned equals for clarity.
  • Use terraform fmt, terraform validate, and editor tooling to maintain consistency.
By following these patterns and conventions, you’ll be able to write maintainable, collaborative Terraform configurations for real-world infrastructure projects.

Watch Video