We already know that we want to describe infrastructure as code (IaC). But there are two ways to do it: the imperative approach and the declarative approach. Understanding this difference is key to understanding how Terraform "thinks" and why it is so convenient. It's a simple concept with an analogy that makes it crystal clear.

The Two Philosophies

  • Imperative: you describe STEP BY STEP how to achieve the result. You give detailed instructions in order: "do this, then this, then that."
  • Declarative: you describe WHAT result you want, and let the tool figure out how to achieve it. You only state the destination, not the path.

Taxi Analogy (the key to everything):

  • Imperative: you give the taxi driver step-by-step directions: "turn right, go straight for 200 meters, at the roundabout take the second exit, turn left...". If you make a mistake in a step, you end up in the wrong place.
  • Declarative: you tell the taxi driver "take me to the airport". He decides the best route. If there's a traffic jam, he finds another way. You only expressed the desired destination.

Terraform is declarative: you declare the destination (the infrastructure you want) and it figures out the steps.

Imperative: "how" to do it

An imperative approach would be, for example, a script (in Bash, Python...) that executes commands in order:

1. Create a network.
2. Create a subnet within the network.
3. Launch a server in the subnet.
4. Configure the server's firewall.
5. ...

Problems with the imperative approach:

  • You manage the order and all dependencies.
  • What happens if you run it twice? It might try to create things that already exist and fail, or duplicate them. You have to write logic to check "does this already exist?" at every step.
  • What if something changes? You have to write more instructions to detect and modify the current state.

It's like step-by-step directions: it works, but you're responsible for every detail and every unexpected event.

Declarative: "what" I want

With the declarative approach (Terraform's), you write the desired final state:

I want:
- A network with this address range.
- A subnet within it.
- A server of this type in that subnet.
- A firewall with these rules.

You don't say in what order to create it or how. You simply declare what you want to exist. Terraform takes care of the rest:

  • Calculates the correct order and dependencies automatically (it knows the subnet goes inside the network, so it creates the network first).
  • Compares what you've declared with what already exists.
  • Makes only the necessary changes so that reality matches your declaration.

The Big Advantage: Idempotence

Here's the key word of the declarative approach: idempotence.

Idempotence means you can apply the same configuration many times and the result is always the same. No matter how many times you run it: if it's already in the desired state, it does nothing; if something is missing, it creates it; if something differs, it adjusts it.

Practical example: You declare that you want "1 server".

  • You apply it: Terraform sees there are none and creates 1.
  • You apply it again (without changing anything): Terraform sees there is already 1 and does nothing. It doesn't create a second server by mistake.
  • You change the declaration to "3 servers" and apply: Terraform sees there is 1 and adds 2 more to reach 3.

You always end up with exactly what you declared. This is the opposite of an imperative script, which could create duplicate servers every time you run it.

Idempotence is what makes declarative IaC safe and predictable. It directly solves the problem of "what happens if I run it again?".

Comparison

Aspect Imperative Declarative (Terraform)
Describes The how (steps) The what (desired result)
Order management You The tool
Idempotent Not by default (you have to program it) Yes, naturally
Change detection Manual Automatic
Example Step-by-step Bash/Python script Terraform, CloudFormation
Analogy Turn-by-turn directions "Take me to the airport"

Is Imperative Bad? No, but...

The imperative approach has its place (one-off scripts, specific automations). But to manage infrastructure, the declarative approach is far superior because:

  • It's easier to read: the code directly describes how everything should end up.
  • It's idempotent and safe to re-run.
  • The tool manages the complexity (order, dependencies, changes) for you.

That's why the main modern IaC tools, including Terraform, are declarative.

Note: some modern tools (like AWS CDK or Pulumi, which we'll see in subchapter 9.3) use regular programming languages, which seem imperative, but underneath generate a declarative model. The important thing is the result: you declare the desired state.

What You Should Remember

  • Imperative: you describe how (the steps, in order). You manage the order and repetitions.
  • Declarative: you describe what you want (the final result). The tool figures out the how. This is the Terraform approach.
  • The analogy: imperative = turn-by-turn directions; declarative = "take me to the airport".
  • The big declarative advantage is idempotence: applying the same configuration many times always gives the same result, with no duplicates or surprises.
  • To manage infrastructure, the declarative approach is more readable, safe, and predictable.

In the next subchapter, we'll compare the most important IaC tools —Terraform, CloudFormation, Pulumi, and CDK— and see why we choose Terraform.

Cloud, AWS & Terraform — From Zero to Expert

Chapter 1 · What is cloud computing

Chapter 2 · The cloud market and major providers

Chapter 3 · Regions, availability zones and edge

Chapter 4 · Compute: EC2

Chapter 5 · Storage: S3

Chapter 6 · Networking: VPC

Chapter 7 · Identity and access: IAM

Chapter 8 · Managed databases

Chapter 9 · Why Infrastructure as Code

Chapter 10 · HCL: the Terraform language

Chapter 11 · Providers and state

Chapter 12 · Your first real infrastructure in Terraform

Chapter 13 · Load balancing and auto scaling

Chapter 14 · Serverless with Lambda

Chapter 15 · Messaging and events

Chapter 16 · Content delivery and DNS

Chapter 17 · Containers on AWS

Chapter 18 · Modules: reuse and composition

Chapter 19 · Workspaces and environment management

Chapter 20 · Remote backends and locking

Chapter 21 · Infrastructure testing

Chapter 22 · Terraform in CI/CD

Chapter 23 · Defense in depth

Chapter 24 · Observability: logs, metrics and traces

Chapter 25 · Cost optimization

Chapter 26 · High availability and disaster recovery

Chapter 27 · AWS Well-Architected Framework

Chapter 28 · Serverless architectures at scale

Chapter 29 · Data platforms on AWS

Chapter 30 · Multi-account and landing zones

Chapter 31 · Platform Engineering and Internal Developer Platform

Chapter 32 · Relevant AWS certifications

Chapter 33 · Projects to consolidate what you've learned

Chapter 34 · Resources and community

© Copyright 2024. All rights reserved