Skip to content

The Terraform Workflow


Terraform’s commands make much more sense when you understand the workflow they form. init, validate, fmt, plan, apply, and destroy are not six unrelated commands. Together they form a cycle in which you prepare a configuration, inspect the proposed changes, apply them, modify the configuration, and eventually remove the infrastructure.

The Terraform Workflow

A useful high-level model is:

    flowchart LR
    A[Write configuration] --> B[terraform fmt]
    B --> C[terraform init]
    C --> D[terraform validate]
    D --> E[terraform plan]
    E --> F[Review plan]
    F --> G[terraform apply]
    G --> H[Infrastructure]
    H --> I[Modify configuration]
    I --> B
    G --> J[terraform destroy]
  

The exact sequence can vary in day-to-day work, but the mental model is important:

You change configuration, Terraform evaluates the change, you review what Terraform proposes, and only then do you apply it.

terraform init

Initialization prepares a working directory for Terraform.

Run:

terraform init

Terraform examines the configuration and installs the providers it needs.

For example, if your configuration requires the random provider, initialization may download that provider into Terraform’s working data.

It also creates or updates the dependency lock file:

.terraform.lock.hcl

and creates the .terraform directory.

Conceptually:

Configuration
     │
     ▼
terraform init
     │
     ├── discover dependencies
     ├── select provider versions
     ├── install providers
     └── create/update lock file

You normally run init when you begin working with a configuration, and again when changes require reinitialization.

For example, changing provider requirements can require another initialization.

terraform fmt

Terraform configurations can be formatted consistently using:

terraform fmt

This command rewrites Terraform configuration files into Terraform’s standard formatting style.

Formatting is not an infrastructure operation. It does not create or modify your infrastructure.

That distinction matters:

terraform fmt
    = modifies configuration formatting

terraform plan
    = proposes infrastructure changes

terraform apply
    = performs infrastructure changes

You can run terraform fmt frequently while editing.

For a project, it is common to format Terraform files before committing them.

terraform validate

Once the configuration is initialized, you can ask Terraform to check whether the configuration is valid:

terraform validate

Validation checks the configuration for syntax and internal consistency problems.

For example, Terraform can detect configuration problems such as malformed blocks or invalid or missing arguments.

A successful validation does not mean Terraform has confirmed that the infrastructure will work exactly as intended.

It means the configuration passes Terraform’s validation rules.

That distinction is important:

validate
    │
    └── Is this configuration valid?

plan
    │
    └── What changes would this configuration require?

terraform plan

The plan is where Terraform’s declarative model becomes visible.

Run:

terraform plan

Terraform evaluates the configuration and determines what it expects to change.

A plan might show:

Plan: 1 to add, 0 to change, 0 to destroy.

The plan is a proposal. It does not normally make the infrastructure changes itself.

This makes the plan valuable for review.

You can ask:

  • Is Terraform creating the resource I expected?
  • Is it changing something I did not intend to change?
  • Is a resource being replaced?
  • Is Terraform going to destroy anything?
  • Did a variable have an unexpected value?

A good Terraform workflow treats the plan as something worth reading rather than as an annoying step before apply.

Create, Update, and Replacement

Terraform can make different kinds of changes.

Suppose the configuration initially describes one resource:

Desired configuration
        │
        ▼
      Resource

If the resource does not exist, Terraform may plan to create it.

Later, you change an argument. If the underlying provider supports changing that property in place, Terraform may plan an update.

Sometimes a property cannot be changed in place. Terraform may instead need to:

destroy old resource
        ↓
create replacement resource

A plan makes this distinction visible.

This is one reason you should not blindly approve plans i.e. a small configuration change does not necessarily imply a small infrastructure change.

terraform apply

After reviewing a plan, you can apply the changes:

terraform apply

Terraform normally shows the proposed changes and asks for confirmation.

When you confirm, Terraform performs the operations necessary to bring the infrastructure toward the desired configuration.

A useful mental model is:

configuration
     │
     ▼
   plan
     │
     ▼
 review
     │
     ▼
  apply
     │
     ▼
infrastructure

Terraform does not simply execute the text of the configuration as a script. It uses its evaluation and planning process to determine the operations required.

A Hands-On Change

Create a directory:

mkdir terraform-workflow
cd terraform-workflow

Create main.tf:

terraform {
  required_providers {
    random = {
      source  = "hashicorp/random"
      version = "~> 3.6"
    }
  }
}

provider "random" {}

resource "random_pet" "name" {
  length    = 2
  separator = "-"
}

output "generated_name" {
  value       = random_pet.name.id
  description = "The generated name."
}

Initialize:

terraform init

Format:

terraform fmt

Validate:

terraform validate

Create a plan:

terraform plan

Apply it:

terraform apply

Confirm with:

yes

Now change the resource:

resource "random_pet" "name" {
  length    = 3
  separator = "-"
}

Run:

terraform plan

Terraform will calculate a new proposed result.

The important part of this exercise is not memorizing length = 3. It is observing the workflow:

Configuration changed
        ↓
terraform plan
        ↓
Terraform evaluates the new desired state
        ↓
Terraform proposes a change

When you are finished:

terraform destroy

Confirm the destruction.

terraform destroy

Destroy removes the infrastructure Terraform manages for the configuration.

Run:

terraform destroy

Terraform generates a destruction plan and asks for confirmation.

This is deliberately similar to terraform apply.

That is because destroy is not a special magic deletion command. Terraform still needs to determine what managed infrastructure exists and what operations are required to remove it.

The mental model is:

terraform apply
    desired state → real infrastructure

terraform destroy
    managed infrastructure → removed infrastructure

Destroy is especially useful for temporary environments and learning exercises.

Warning

terraform destroy is a real infrastructure operation. Never run it against a configuration until you understand which resources it manages and have reviewed the proposed destruction.

Why Terraform Does Not Run .tf Files Top to Bottom

If you come from a scripting background, you may naturally expect:

line 1
line 2
line 3
line 4

Terraform does not work that way.

Terraform configuration describes resources and values. Terraform evaluates that configuration and determines dependencies between things.

For example:

resource "example_network" "main" {
  # ...
}

resource "example_server" "web" {
  network_id = example_network.main.id
}

The server refers to the network’s ID.

Terraform can therefore understand that the server depends on the network.

The important relationship is:

network
   │
   │ id
   ▼
server

not:

network block appears before server block

The first relationship is meaningful to Terraform. File ordering by itself is not.

You will study dependency evaluation in much greater depth later in the course. For now, simply remember that Terraform is declarative rather than a line-by-line provisioning script.

A Useful Daily Workflow

For a normal configuration change, a practical sequence is:

terraform fmt
terraform validate
terraform plan
terraform apply

If the working directory has not been initialized, run:

terraform init

before validation and planning.

For destructive changes, pay particular attention to the plan.

A useful habit is:

Never treat terraform plan as noise. It is the explanation of what Terraform believes your configuration change means for real infrastructure.

You now have the basic Terraform lifecycle: initialize dependencies, format and validate configuration, generate a plan, apply changes, modify configuration, and eventually destroy the managed infrastructure.

The next chapter looks at the pieces Terraform is actually managing: providers, resources, and the Terraform Registry.

Last updated on