Terraform Advanced — Account-Per-Environment

less than 1 minute read

Use separate AWS accounts for blast-radius isolation.


The Pattern

AWS Organization
├── Management Account (billing, org policies)
├── Security Account (CloudTrail, GuardDuty)
├── Shared Services (CI/CD, artifact repos)
├── Dev Account
├── Staging Account
└── Prod Account

Terraform with assume_role

# In CI/CD — assume into the target account
provider "aws" {
  region = "us-east-1"
  assume_role {
    role_arn = "arn:aws:iam::${var.target_account_id}:role/terraform-deploy"
  }
}

Account Vending with Terraform

resource "aws_organizations_account" "dev" {
  name  = "dev"
  email = "aws-dev@example.com"
  parent_id = aws_organizations_organizational_unit.workloads.id

  lifecycle {
    prevent_destroy = true
  }
}

# Baseline each account
module "account_baseline" {
  source     = "./modules/account-baseline"
  account_id = aws_organizations_account.dev.id
  # Sets up: CloudTrail, Config, GuardDuty, default VPC deletion
}

Benefits

✅ Blast radius: dev mistake can't affect prod
✅ Billing: clear cost attribution per environment
✅ Security: SCPs limit what each account can do
✅ Quotas: independent service limits per account

💡 Production Tip: Use AWS Service Control Policies (SCPs) to prevent dangerous actions in non-prod accounts, like creating expensive instance types.


What’s Next?

Deploy without downtime.

← Three-Tier Repo Zero-Downtime Deployments →

Updated: