Skip to main content

Parallelism

Terraform run operations แบบ parallel อยู่แล้ว — ปรับ -parallelism flag เพื่อ tune speed vs API rate limits

Default Parallelism

ทุก plan/apply Terraform รัน 10 operations concurrent:

terraform apply
# → up to 10 resources created in parallel

Adjust Parallelism

# เพิ่มเป็น 20
terraform apply -parallelism=20

# ลดเป็น 5 (สำหรับ provider rate-limited)
terraform apply -parallelism=5

เมื่อไหร่ควรเพิ่ม?

  • ✅ Infrastructure ใหญ่ (100+ resources)
  • ✅ Apply ช้าและไม่ติด rate limit
  • ✅ Cloud provider แข็งแรง (AWS, GCP, Azure)

เมื่อไหร่ควรลด?

  • ❌ Hit API rate limits
  • ❌ Provider error: Throttling exception
  • ❌ Dependent resources race condition
  • ❌ Provider ที่ไม่ stable (community)

ดู Parallelism in Action

$ terraform apply -parallelism=20

aws_subnet.public[0]: Creating...
aws_subnet.public[1]: Creating...
aws_subnet.public[2]: Creating...
aws_subnet.private[0]: Creating...
aws_subnet.private[1]: Creating...
aws_subnet.private[2]: Creating...
# 20 resources running concurrently

Rate Limit Errors

ถ้าเจอ:

Error: Throttling: Rate exceeded
status code: 400, request id: ...

แก้:

# 1. ลด parallelism
terraform apply -parallelism=5

# 2. Retry (Terraform retry บางส่วนอัตโนมัติ)
terraform apply

Provider-Specific Rate Limits

AWS

  • Most APIs: ~100-500 req/sec ต่อ region
  • Some APIs (RDS, IAM): lower
  • IAM specifically: 5-20 req/sec
provider "aws" {
region = "ap-southeast-1"

# Custom retry config
max_retries = 25

default_tags { ... }
}

GCP

  • Default: 60 req/min (per user)
  • Increase via quota requests

Azure

  • ARM API: ~1200 req/hour per subscription

Adaptive Strategy

# Start fast
terraform apply -parallelism=20

# If errors, drop to default
terraform apply

# If still errors, drop more
terraform apply -parallelism=5

Per-Operation Tuning

ไม่สามารถตั้งต่อ resource — -parallelism ใช้ทั้ง plan/apply

แต่ใช้ -target แยก apply เป็น phases:

# Phase 1: Network (low parallelism — sensitive)
terraform apply -target=module.network -parallelism=5

# Phase 2: Compute (high parallelism)
terraform apply -target=module.compute -parallelism=20

# Phase 3: Final apply
terraform apply

Concurrency in Provider

ก่อน Terraform parallelism — provider ก็ทำ concurrent calls:

provider "aws" {
# AWS provider จะใช้ http connection pool
}

ลด throttling ระดับ provider:

provider "aws" {
retry_mode = "adaptive" # Adaptive retry (handle rate limit)
max_retries = 25
}

Refresh Parallelism

terraform refresh (และ plan's implicit refresh) ก็ใช้ parallelism:

terraform plan -refresh-only -parallelism=20

ถ้า plan ช้า — มักเป็น refresh phase (อ่าน 100+ resources จาก provider)

แก้:

  1. เพิ่ม parallelism
  2. ใช้ -refresh=false (skip refresh — ระวัง drift!)
terraform plan -refresh=false   # plan แค่ตาม config + state

Plan Performance Tips

1. Targeted Plan

terraform plan -target=aws_instance.web   # plan เฉพาะ resource

2. Skip Refresh

terraform plan -refresh=false   # ไม่อ่าน reality (faster but stale)

3. Split State

ถ้า plan > 30s → split state (ดู Splitting Large State)

4. Cache Provider

export TF_PLUGIN_CACHE_DIR=$HOME/.terraform.d/plugin-cache
mkdir -p $TF_PLUGIN_CACHE_DIR

→ ลดเวลา init จาก 30s → 5s

ตัวอย่าง: Performance Benchmarks

# Small state (10 resources)
$ time terraform plan
real 0m3.2s # default parallelism = OK

# Large state (200 resources)
$ time terraform plan -parallelism=10
real 0m45s

$ time terraform plan -parallelism=20
real 0m25s # 1.8x faster

$ time terraform plan -parallelism=30
real 0m24s # diminishing returns

Gotchas

1. Order Matters Sometimes

Parallel ≠ unordered. Terraform หา dependency แล้วทำตาม order:

resource "aws_vpc" "main" { ... }       # ✅ first

resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id # depends on VPC
count = 3 # ✅ 3 subnets parallel
}

VPC สร้างก่อน → 3 subnets parallel

2. Dependent Resources Wait

[VPC] → [Subnet A] [Subnet B] [Subnet C]    (parallel)
↓ ↓ ↓
[SG A] [SG B] [SG C] (parallel หลัง subnet)

Terraform คำนวณ DAG อัตโนมัติ

3. Implicit Dependency Misses

resource "aws_iam_role" "lambda" { ... }
resource "aws_iam_role_policy" "lambda" { ... }

resource "aws_lambda_function" "x" {
role = aws_iam_role.lambda.arn
# ❌ Missing: depends_on = [aws_iam_role_policy.lambda]
}

Lambda might run before policy attached → fail

แก้:

depends_on = [aws_iam_role_policy.lambda]

Best Practices

✅ DO:
- ใช้ default parallelism (10) ก่อน
- เพิ่มถ้า apply ช้า + ไม่ rate limited
- ลดถ้าเจอ throttling
- ใช้ targeted apply ใน emergency
- Cache provider plugins

❌ DON'T:
- ห้ามตั้ง parallelism สูงเกิน (>50) — มักไม่ช่วย + อันตราย
- ห้ามใช้ -refresh=false ใน prod (drift!)
- ห้าม skip dependency declarations เพื่อหวัง parallel

Concurrency Patterns

Multi-Stack Parallel (ผ่าน Terragrunt)

# Apply ทุก stack ที่ไม่มี dependency กัน — parallel
terragrunt run-all apply --terragrunt-parallelism 10

→ Multiple stack apply พร้อมกัน

Multi-Region Parallel

# Region 1
cd us-east-1 && terraform apply -auto-approve &

# Region 2
cd ap-southeast-1 && terraform apply -auto-approve &

# Wait
wait

(ระวัง state lock + console output mixing)

สรุป

  • Default parallelism = 10
  • Tune ด้วย -parallelism=N
  • เพิ่มเมื่อ apply ช้า + ไม่ rate limit, ลดเมื่อ throttling
  • -refresh=false skip refresh (faster but stale)
  • Cache provider plugins ลดเวลา init
  • Use Terragrunt สำหรับ multi-stack parallel

ต่อไป → Deployment Workflow