Mastering HCL: Terraform's Configuration Language

My journey from basic syntax to advanced HCL patterns that make infrastructure elegant


Table of Contents


Introduction: The Day I Discovered HCL's True Power

I was three months into using Terraform, and my configurations were working but ugly. Really ugly. Lots of repetition, hardcoded values, and what I call "infrastructure spaghetti."

Then I saw a senior engineer's Terraform code. It was beautiful. Dynamic, elegant, with no repetition. One configuration that handled 20 different scenarios with conditional logic, loops, and computed values.

"How did you do this?" I asked.

"HCL," they said. "You're barely scratching the surface."

They were right. I'd been using Terraform like a templating engine when it was actually a powerful programming language. That conversation sent me down a rabbit hole of learning HCL's advanced features: for expressions, dynamic blocks, conditional logic, and the 50+ built-in functions.

This article is everything I wish someone had taught me on day one. We're going deep into HashiCorp Configuration Language to transform your Terraform code from basic to elegant.


What is HCL?

HCL (HashiCorp Configuration Language) is Terraform's native configuration language. It's designed to be:

  • Human-readable - Looks like configuration, not code

  • Declarative - Describe what you want, not how to create it

  • Expressive - Powerful enough for complex scenarios

  • Consistent - Same syntax across all HashiCorp tools

HCL vs JSON vs YAML

Why HCL wins:

  • Comments are better (# and // supported)

  • String interpolation built-in

  • Better support for expressions

  • More readable for infrastructure definitions


HCL Syntax Fundamentals

Let's master the building blocks of HCL.

Blocks

Examples:

Arguments

Comments


Expressions and References

Expressions are how you compute values in HCL.

Simple Expressions

References

Attribute Access


String Templates and Interpolation

HCL's string interpolation is powerful and flexible.

Basic Interpolation

Multi-line Strings (Heredoc)

String Directives

Interpolation directive:

Strip whitespace directive:

Conditional directive:

Loop directive:

Template Functions


Conditional Expressions

Terraform's ternary operator enables conditional logic.

Basic Conditional

Conditional Resource Creation

Nested Conditionals

Conditional with Complex Logic


For Expressions

For expressions transform lists and maps. They're incredibly powerful.

List Transformation

Basic for loop:

With conditionals:

With index:

Map Transformation

Create map from list:

Transform map:

Complex map transformation:

Nested For Expressions


Splat Expressions

Splat expressions are shorthand for getting attributes from all items.

Basic Splat

Splat with for_each

Conditional Splat


Local Values

Locals let you define named computed values that can be reused.

Basic Locals

Complex Locals

Locals Referencing Locals


Built-in Functions

Terraform has 100+ built-in functions. Let's explore the most useful ones.

String Functions

Numeric Functions

Collection Functions

Map Functions

Encoding Functions

Filesystem Functions

Date and Time Functions

Type Conversion Functions

Advanced Functions


Dynamic Blocks

Dynamic blocks generate repeated nested blocks.

Basic Dynamic Block

Without dynamic (repetitive):

With dynamic (elegant):

Complex Dynamic Blocks

Security group rules example:

Nested Dynamic Blocks

Conditional Dynamic Blocks


Complex Expression Patterns

Let's combine everything we've learned into advanced patterns.

Pattern 1: Environment-Specific Configuration

Pattern 2: Resource Naming Convention

Pattern 3: Tag Standardization

Pattern 4: Feature Flags with Validation


Real-World Example: Advanced Blog Platform

Let's build a sophisticated blog platform using advanced HCL.

Project Structure

variables.tf

locals.tf

main.tf

environments/production.tfvars

Deploy


Common Mistakes and How to Avoid Them

Mistake #1: Overusing Ternary Operators

Bad:

Good:

Mistake #2: Not Using Locals for Repeated Expressions

Bad:

Good:

Mistake #3: Incorrect For Expression Syntax

Bad:

Good:

Mistake #4: Trying to Use Variables in terraform {} Block

Bad:

Good:

Mistake #5: Forgetting Type Conversions

Bad:

Good:


Best Practices for HCL

1. Use Locals for Complex Expressions

2. Prefer Maps Over Nested Ternaries

3. Use For Expressions for Transformations

4. Comment Complex Expressions

5. Extract Magic Numbers to Variables


What I Learned About HCL Mastery

1. HCL is More Powerful Than It Looks

When I started, I thought HCL was just a configuration format. It's actually a full expression language with:

  • 100+ built-in functions

  • List and map comprehensions

  • Conditional logic

  • Type system

  • Template rendering

2. Locals Are Your Best Friend

Locals let you:

  • Name complex expressions

  • Reuse computations

  • Document intent

  • Reduce duplication

Use them liberally!

3. For Expressions Replace Most Loops

Instead of creating resources with count or for_each, use for expressions to transform data first:

4. Functions Are Composable

Chain functions for powerful transformations:

5. Dynamic Blocks Are Last Resort

Use dynamic blocks only when necessary. Often there's a better way:


Next Steps

Congratulations! You've mastered HCL:

✅ HCL syntax fundamentals ✅ Expressions and references ✅ String templates and interpolation ✅ Conditional expressions ✅ For expressions and splat ✅ Local values ✅ 100+ built-in functions ✅ Dynamic blocks ✅ Advanced blog platform with complex HCL

Practice Exercises

Exercise 1: For Expressions

Exercise 2: Function Chaining

Exercise 3: Dynamic Configuration

Coming Up Next

In Article 5: Modules - Building Reusable Infrastructure Components, we'll learn:

  • What modules are and why they matter

  • Creating custom modules

  • Module inputs and outputs

  • Module composition

  • Terraform Registry

  • Versioning and publishing modules

HCL is the language. Modules are how you organize that language into reusable, composable infrastructure components.


This Week's Challenge: Refactor your existing Terraform configurations to use for expressions, locals, and functions. Eliminate all code duplication. Make it elegant.

See you in Article 5! 🎨


"HCL transformed my Terraform from simple templating to elegant programming. The day I discovered for expressions and local values was the day my infrastructure code became beautiful." - Me, after refactoring 2,000 lines down to 400

Last updated