HashiCorp Terraform, an open-source Infrastructure as Code (IaC) tool, enables easier infrastructure provisioning and management across all types of platforms. At the heart of Terraform’s effectiveness is its workflow that consists of three main stages: Write, Plan, and Apply. This provides a structured process that ensures a seamless creation, modification, and provisioning process for managing infrastructure more easily, quickly, and reliably.

In this article, we’ll take a look at the three stages of the Terraform Workflow and how each stage is managed. Whether you’re a solo practitioner or part of a larger team, understanding the Terraform Workflow process is key to achieving efficient, scalable, and reproducible infrastructure management automation within an overall DevOps process.

The stages of the Terraform Workflow process are explained further in this article, but here’s a short “TLDR;” discription of the three key stages:

  1. Write – Develop infrastructure as code (IaC) configuration to define the infrastructure to be provisioned and managed.
  2. Plan – Preview the modifications necessary before implementation as a means to verify changes before applying them to the infrastructure environment.
  3. Apply – Reliably and scalably apply infrastructure changes in an automated fashion to ensure continuity across environments.

Stage 1: Write Terraform Code

The first state in the Terraform Workflow process is to “Write Terraform code”. This is the state that you will start with as you write the Terraform code that describes the infrastructure resource configurations to be managed by the Terraform project.

Need help learning Terraform? If you need an introduction or more on writing HashiCorp Terraform code for provisioning, configuring and managing resources, a good place to start is the “Get Started with Terraform” article written by Chris Pietschmann.

As an Infrastructure as Code (IaC) tool, HashiCorp Terraform, uses a “declarative syntax” for provisioning infrastructure resources. This means the Terraform code will declare the desired state and configuration of the resources, then the Terraform tool will use the Terraform Provider to make the necessary infrastructure changes to make the infrastructure deployment match the declared state once the deployment (aka terraform apply explained down below) has been completed.

With Terraform being a “declarative syntax”, this enables you to look at the Terraform code to be able to tell how the infrastructure provisioned and managed by the Terraform project should be configured. This will be more clear when we look at the Plan stage (via terraform plan explained down below) of the Terraform Workflow process.

To keep things short here, the following is a very brief Terraform project that will provision and manage an Azure Resource Group, and store the Terraform State File (.tfstate) in an Azure Storage Account:

terraform {
  required_providers {
    # specify the Terraform Azure Provider version to use
    azurerm = {
      source = "hashicorp/azurerm"
      version = "=2.46.0"
  # Define the backend Terraform State (.tfstate file) storage
  # to be in Azure Storage Account
  backend "azurerm" {
    resource_group_name  = "app1-tfstate-rg"
    storage_account_name = "app1tfstatesa"
    container_name       = "tfstate"
    key                  = "terraform.tfstate"

# define the Microsoft Azure provider
provider "azurerm" {
  features {}

# Create a resource group
resource "azurerm_resource_group" "b59" {
  name     = "b59-rg"
  location = "North Central US"

Terraform projects for managing the infrastructure for an application or ogranization will be much larger than this example. However, those should give you an idea of what the Terraform code might look like to get started.

Security Best Practice: When managing Microsoft Azure and other resources using Terraform, it is supported and acceptable to use an Azure Storage Account to store the State File (.tfstate). However, due to secuity requirements that need to be met to do so safely and securely (because there are secrets stored in the state file itself!) you may want to consider using HashiCorp’s Terraform Cloud to manage Terraform deployments and storing the Terraform State file more securely.

Once the Terraform code is written, the standard practice is to store the files in a source control repository. Generally, Git is used, but it could be another system your team uses. The following “Plan” stage is usually executed through the use of some sort of CI/CD pipeline as part of an overall DevOps process as well.

Stage 2: Plan Infrastructure Changes

During the “Plan” stage of the Terraform Workflow process, the terraform plan command is used to plan what changes need to be made to the managed infrastructure so that it matches the current state of configuration as defined by the Terraform code.

Before running the plan command, the init command must be run. The init command initializes the Terraform project and performs required tasks such as downloading the Terraform Providers used within the project. After the project is initialized, then the plan command can be run to assess the managed infrastructure and figure out the plan of changes to make.

$ terraform init
$ terraform plan

Once the terraform plan command is run, it will output the plan so you can review it. This plan will include the details of what configuration changes will be made when the apply command (covered down below) is executed.

The following is a brief example of a Terraform plan output:

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.b59 will be created
  + resource "azurerm_resource_group" "b59" {
      + id       = (known after apply)
      + location = "northcentralus"
      + name     = "b59-rg"

  # azurerm_storage_account.example will be created
  + resource "azurerm_storage_account" "example" {
      + access_tier                      = (known after apply)
      + account_kind                     = "StorageV2"
      + account_replication_type         = "GRS"

When the terraform plan command is executed, Terraform will read the Terraform State (.tfstate) file for the project, and use that file to help determine what the necessary changes are for the final plan. The state file is used by Terraform as a way to remember the current configuration of the infrastructure managed by the Terraform project. Due to how Terraform uses the state file, it’s important that when managing infrastructure using Terraform that you no longer manually change any infrastructure resources managed by the Terraform project. If resources are managed by Terraform, they should only be managed by Terraform going forward.

Need help adopting infrastructure resources into Terraform? If you have existing infrastructure resources that you want to adopt into your Terraform project and start managing them with Terraform, then I recommend you read the article “Terraform: Import Existing Infrastructure” written by Chris Pietschmann.

Stage 3: Apply Infrastructure Changes / Provision Resources

The Apply stage is the final stage of the Terraform Workflow process. This is the stage where the Terraform configuration will be applied to an infrastructure environment to provision new resources and reconfigure existing resources so they match the declared configuration within the Terraform project.

The Terraform apply command is executed after the init and plan commands have already been executed. When this command is executed, Terraform will use the specified Terraform Providers to interact with the necessary platforms for the declared resources to perform the provisioning and configuration tasks necessary.

$ terraform apply

Once the terraform apply command has finished executing any infrastructure changes, it will modify the Terraform State (.tfstate) file, so it contains the currently configured state of the infrastructure managed by Terraform.

Repeat it over again!

The Terraform Workflow process of Write, Plan, and Apply is really an iterative process to follow as you manage the infrastructure through Terraform going forward. As new infrastructure needs to be provisioned and reconfigured, the necessary Terraform code changes will need to be made to the Terraform project by repeating the “Write” stage. Then, the “Plan” and “Apply” stages will be repeated to perform the necessary provisioning and management process to manage those resources.


Basically, the Terraform Workflow process is Write, Plan, Apply, Repeat as you manage infrastructure through a repeatable and reliable process using Infrastructure as Code (IaC). Terraform isn’t the only IaC tool available, but it’s one of the most popular and most versatile tools as it supports over 1,000 Terraform Providers for managing all kinds of different infrastructure all from within the same Terraform project if necessary.

Happy Terraform-ing!

Microsoft MVP

Chris Pietschmann is a Microsoft MVP, HashiCorp Ambassador, and Microsoft Certified Trainer (MCT) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to large enterprises. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.
HashiCorp Ambassador Microsoft Certified Trainer (MCT) Microsoft Certified: Azure Solutions Architect