Skip to content

Terraform Modules and State

The two decisions that make or break a Terraform codebase are: how you split state and how you compose modules. Everything else is tabs vs spaces.

  • Directoryinfra/
    • Directorymodules/
      • Directorynetwork/
        • main.tf
        • variables.tf
        • outputs.tf
        • versions.tf
      • Directorykubernetes/
      • Directorypostgres/
    • Directoryenvs/
      • Directorydev/
        • main.tf
        • terraform.tfvars
        • backend.tf
      • Directorystaging/
      • Directoryprod/
    • .tflint.hcl
    • .terraform-docs.yml
modules/network/main.tf
terraform {
required_version = ">= 1.9.0"
required_providers {
azurerm = { source = "hashicorp/azurerm", version = "~> 4.0" }
}
}
variable "name" {
type = string
description = "Prefix for created resources."
}
variable "address_space" {
type = list(string)
default = ["10.0.0.0/16"]
}
resource "azurerm_virtual_network" "this" {
name = "${var.name}-vnet"
location = var.location
resource_group_name = var.resource_group_name
address_space = var.address_space
tags = var.tags
}
output "vnet_id" {
value = azurerm_virtual_network.this.id
}
envs/prod/backend.tf
terraform {
backend "azurerm" {
resource_group_name = "tfstate-rg"
storage_account_name = "reetwiztfstate"
container_name = "prod"
key = "network.tfstate"
use_azuread_auth = true
}
}
  1. Root-per-env (recommended). One root module per env, calls shared child modules.
  2. Workspaces. One root, many terraform workspaces. Simple, but env drift is easy — a terraform apply on the wrong workspace is production. Avoid for anything past 2 envs.
  3. Terragrunt / stacks. External tool wraps the DRY problem. Powerful, another moving part.

Terraform 1.5+ has native import blocks — you no longer need terraform import:

import.tf
import {
to = azurerm_resource_group.core
id = "/subscriptions/xxx/resourceGroups/core-rg"
}
resource "azurerm_resource_group" "core" {
name = "core-rg"
location = "westeurope"
}

Then terraform plan -generate-config-out=generated.tf and you get the HCL for free.