← Back to Terraform

Multi-Environment Management with Terraform

Maintaining consistent infrastructure across development, staging, and production environments with minimal code duplication.

Overview

Terraform enables managing multiple environments efficiently by using variables, workspaces, and modules. A single configuration can be deployed to different environments with appropriate scaling and resource configurations.

Environment Structure with Workspaces

HCL - main.tf with Workspace Support
terraform {
  required_version = ">= 1.0"
  cloud {
    organization = "my-org"
    workspaces {
      name = terraform.workspace
    }
  }
}

locals {
  env = terraform.workspace
  
  env_config = {
    dev = {
      instance_count = 1
      machine_type   = "e2-medium"
      disk_size      = 20
      enable_backup  = false
      labels = { env = "dev", cost_center = "dev" }
    }
    staging = {
      instance_count = 2
      machine_type   = "e2-standard-2"
      disk_size      = 50
      enable_backup  = true
      labels = { env = "staging", cost_center = "qa" }
    }
    prod = {
      instance_count = 5
      machine_type   = "e2-standard-4"
      disk_size      = 100
      enable_backup  = true
      labels = { env = "prod", cost_center = "prod" }
    }
  }

  config = local.env_config[local.env]
}

# Compute resources based on environment
resource "google_compute_instance" "app" {
  count         = local.config.instance_count
  name          = "${local.env}-app-${count.index}"
  machine_type  = local.config.machine_type
  zone          = "${var.gcp_region}-a"

  boot_disk {
    initialize_params {
      size  = local.config.disk_size
      image = "projects/debian-cloud/global/images/debian-11"
    }
  }

  labels = local.config.labels

  metadata_startup_script = <<-EOT
    #!/bin/bash
    echo "Environment: ${local.env}"
  EOT
}

# Database configuration per environment
resource "google_sql_database_instance" "db" {
  name             = "${local.env}-database"
  database_version = "POSTGRES_15"

  settings {
    tier      = local.config.machine_type == "e2-medium" ? "db-f1-micro" : "db-standard-2"
    disk_size = local.config.disk_size

    backup_configuration {
      enabled      = local.config.enable_backup
      location     = var.gcp_region
      point_in_time_recovery_enabled = local.env == "prod"
    }

    database_flags {
      name  = "log_statement"
      value = local.env == "prod" ? "all" : "none"
    }
  }

  deletion_protection = local.env == "prod"
}

Variables Per Environment

HCL - terraform.tfvars (development)
gcp_project = "my-company-dev"
gcp_region  = "us-central1"

# Development-specific settings
app_image_tag = "latest"
enable_monitoring = false
replica_count = 1
HCL - terraform.tfvars (production)
gcp_project = "my-company-prod"
gcp_region  = "us-central1"

# Production-specific settings
app_image_tag = "v1.5.0"
enable_monitoring = true
replica_count = 5

Module-Based Environment Management

HCL - Directory Structure
terraform/
├── modules/
│   ├── app_service/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── database/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   └── terraform.tfvars
│   ├── staging/
│   │   ├── main.tf
│   │   └── terraform.tfvars
│   └── prod/
│       ├── main.tf
│       └── terraform.tfvars
└── shared/
    ├── variables.tf
    └── outputs.tf

Environment Module Usage

HCL - environments/prod/main.tf
terraform {
  backend "gcs" {
    bucket = "my-company-terraform-state"
    prefix = "prod"
  }
}

module "app_service" {
  source = "../../modules/app_service"

  environment    = "prod"
  replica_count  = 5
  machine_type   = "e2-standard-4"
  enable_ssl     = true
  enable_cdn     = true
  
  labels = {
    environment = "prod"
    managed     = "terraform"
    cost_center = "engineering"
  }
}

module "database" {
  source = "../../modules/database"

  environment = "prod"
  db_tier     = "db-standard-2"
  disk_size   = 100

  backup_config = {
    enabled = true
    location = "us"
    point_in_time_recovery = true
  }

  labels = module.app_service.labels
}

output "app_url" {
  value = module.app_service.url
}

output "database_connection_name" {
  value = module.database.connection_name
}

Best Practices