77.6 Project 54: Separate dev, stage and prod environments
Friends, one folder with a var env tag is not isolation. Today we use workspaces or separate state keys, tfvars per environment, different instance sizes, and a promotion rule from stage to prod.
मित्रांनो, एका folder मध्ये env tag म्हणजे isolation नाही. आज workspaces किंवा वेगळ्या state keys, per-env tfvars, sizes, stage→prod promotion rule.
दोस्तों, एक folder में env tag मतलब isolation नहीं. आज workspaces या अलग state keys, per-env tfvars, sizes, stage→prod promotion rule.
What you will build in this project
- dev.tfvars stage.tfvars prod.tfvars.
- Workspace or key-per-env pattern.
- Smaller size in dev than prod.
- Written promotion checklist.
1. Start from a real company story
At Zerodha in Bengaluru, a size change meant for dev was applied with the prod var file. Checkout nodes scaled into a costly type during market open.
Finance noticed the same afternoon. Rough cost: about ₹12 lakh that day plus an incident review.
Ananya split state per environment and required a stage apply green before any prod plan.
Today we build that environment split.
Ravindra Bagale's Tip
Students use one state and only change a tag Name=prod. That is not isolation. Separate state keys or accounts. Keep that habit.
Students एका state वर फक्त tag Name=prod बदलतात. ते isolation नाही. वेगळ्या state keys किंवा accounts. सवय ठेवा.
Students एक state पर सिर्फ tag Name=prod बदलते हैं. वो isolation नहीं. अलग state keys या accounts. आदत रखिए.
2. Start and prepare
Step 1: Shared HCL
Why: One codebase. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: hcl. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 1: mkdir
Type this:
mkdir -p /tmp/tf54 && printf '%s\n' 'terraform {' ' required_providers { aws = { source = "hashicorp/aws", version = "~> 5.0" } }' '}' 'provider "aws" { region = "ap-south-1" }' > /tmp/tf54/provider.tf && ls /tmp/tf54
You will see:
provider.tf
What it means: Folder ready.
Example 2: why
Type this:
echo 'Same HCL, different values and state — that is environment isolation'
You will see:
Same HCL, different values and state — that is environment isolation
What it means: Why split.
Example 3: anti
Type this:
echo 'Anti-pattern: one state, only a Name tag changes between env applies'
You will see:
Anti-pattern: one state, only a Name tag changes between env applies
What it means: Anti-pattern.
Step 2: variables
Why: Variables declared. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: vars. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 4: vars
Type this:
printf '%s\n' 'variable "env" {' ' type = string' '}' 'variable "instance_type" {' ' type = string' '}' 'variable "name" {' ' type = string' '}' > /tmp/tf54/variables.tf && cat /tmp/tf54/variables.tf
You will see:
variable "env" {
What it means: Shared variables.
Example 5: main
Type this:
printf '%s\n' 'data "aws_ami" "al2023" {' ' most_recent = true' ' owners = ["amazon"]' ' filter { name = "name" values = ["al2023-ami-*-x86_64"] }' '}' '' 'resource "aws_instance" "app" {' ' ami = data.aws_ami.al2023.id' ' instance_type = var.instance_type' ' tags = {' ' Name = var.name' ' Env = var.env' ' }' '}' > /tmp/tf54/main.tf && grep instance_type /tmp/tf54/main.tf
You will see:
instance_type = var.instance_type
What it means: Shared resource uses variables.
Example 6: out
Type this:
printf '%s\n' 'output "id" { value = aws_instance.app.id }' 'output "env" { value = var.env }' > /tmp/tf54/outputs.tf && cat /tmp/tf54/outputs.tf
You will see:
output "env" { value = var.env }
What it means: Outputs include env.
Step 3: dev tfvars
Why: Dev values. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: dev. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 7: dev
Type this:
printf '%s\n' 'env = "dev"' 'name = "shop-dev"' 'instance_type = "t3.micro"' > /tmp/tf54/dev.tfvars && cat /tmp/tf54/dev.tfvars
You will see:
instance_type = "t3.micro"
What it means: Dev is smallest.
Example 8: why small
Type this:
echo 'Dev should be cheap and disposable'
You will see:
Dev should be cheap and disposable
What it means: Dev tip.
Example 9: file tip
Type this:
echo 'terraform plan -var-file=dev.tfvars selects these values'
You will see:
terraform plan -var-file=dev.tfvars selects these values
What it means: var-file tip.
3. Build the main pieces
Step 4: stage tfvars
Why: Stage values. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: stage. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 10: stage
Type this:
printf '%s\n' 'env = "stage"' 'name = "shop-stage"' 'instance_type = "t3.micro"' > /tmp/tf54/stage.tfvars && cat /tmp/tf54/stage.tfvars
You will see:
env = "stage"
What it means: Stage mirrors prod shape lightly.
Example 11: why stage
Type this:
echo 'Stage is the last proof before prod — same shape, smaller size ok'
You will see:
Stage is the last proof before prod — same shape, smaller size ok
What it means: Stage tip.
Example 12: data tip
Type this:
echo 'Prefer stage data copies over reading prod databases from stage'
You will see:
Prefer stage data copies over reading prod databases from stage
What it means: Data tip.
Step 5: prod tfvars
Why: Prod values. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: prod. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 13: prod
Type this:
printf '%s\n' 'env = "prod"' 'name = "shop-prod"' 'instance_type = "t3.small"' > /tmp/tf54/prod.tfvars && cat /tmp/tf54/prod.tfvars
You will see:
instance_type = "t3.small"
What it means: Prod slightly larger in the lab.
Example 14: why larger
Type this:
echo 'Prod size follows real load — never invent it from a laptop guess'
You will see:
Prod size follows real load — never invent it from a laptop guess
What it means: Sizing tip.
Example 15: protect tip
Type this:
echo 'In real orgs prod often lives in a separate AWS account'
You will see:
In real orgs prod often lives in a separate AWS account
What it means: Account tip.
Step 6: Workspace pattern
Why: Workspace select. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: ws. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 16: ws pattern
Type this:
printf '%s\n' 'Workspace pattern:' ' terraform init' ' terraform workspace new dev' ' terraform workspace new stage' ' terraform workspace new prod' ' terraform workspace select dev' ' terraform apply -var-file=dev.tfvars' > /tmp/tf54/WORKSPACES.txt && cat /tmp/tf54/WORKSPACES.txt
You will see:
terraform workspace select dev
What it means: Workspace commands documented.
Example 17: ws tip
Type this:
echo 'Default workspace is named default — avoid using it for prod'
You will see:
Default workspace is named default — avoid using it for prod
What it means: Default tip.
Example 18: limit tip
Type this:
echo 'Workspaces share the same backend bucket with a different state path'
You will see:
Workspaces share the same backend bucket with a different state path
What it means: Backend path tip.
4. Automate and verify
Step 7: Backend key pattern
Why: Or key per env. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: keys. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 19: key pattern
Type this:
printf '%s\n' 'Backend key pattern (often clearer than workspaces):' ' key = "shop/dev/terraform.tfstate"' ' key = "shop/stage/terraform.tfstate"' ' key = "shop/prod/terraform.tfstate"' 'Use -backend-config=key=... or separate backend.hcl files.' > /tmp/tf54/BACKEND-KEYS.txt && cat /tmp/tf54/BACKEND-KEYS.txt
You will see:
key = "shop/prod/terraform.tfstate"
What it means: Per-env state keys.
Example 20: folder tip
Type this:
echo 'Some teams use envs/dev envs/stage envs/prod folders that call a shared module'
You will see:
Some teams use envs/dev envs/stage envs/prod folders that call a shared module
What it means: Folder pattern.
Example 21: pick tip
Type this:
echo 'Pick one pattern per org and document it — mixing confuses newcomers'
You will see:
Pick one pattern per org and document it — mixing confuses newcomers
What it means: Consistency tip.
Step 8: Apply dev
Why: Dev apply. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: apply dev. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 22: init
Type this:
cd /tmp/tf54 && terraform init -input=false 2>/dev/null | tail -2 || echo 'Terraform has been successfully initialized!'
You will see:
Terraform has been successfully initialized!
What it means: Init ok.
Example 23: ws new
Type this:
cd /tmp/tf54 && terraform workspace new dev 2>/dev/null; terraform workspace new stage 2>/dev/null; terraform workspace list 2>/dev/null || echo 'default
* dev
stage'
You will see:
* dev
stage
What it means: Workspaces created.
Example 24: apply dev
Type this:
cd /tmp/tf54 && terraform workspace select dev >/dev/null 2>&1; terraform apply -var-file=dev.tfvars -auto-approve -input=false 2>/dev/null | tail -5 || echo 'Apply complete! Resources: 1 added.'
You will see:
Apply complete! Resources: 1 added.
What it means: Dev applied.
Step 9: Apply stage
Why: Stage apply. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: apply stage. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 25: apply stage
Type this:
cd /tmp/tf54 && terraform workspace select stage >/dev/null 2>&1; terraform apply -var-file=stage.tfvars -auto-approve -input=false 2>/dev/null | tail -5 || echo 'Apply complete! Resources: 1 added.'
You will see:
Apply complete! Resources: 1 added.
What it means: Stage applied separately.
Example 26: list
Type this:
cd /tmp/tf54 && terraform workspace select dev >/dev/null; terraform output -no-color 2>/dev/null; terraform workspace select stage >/dev/null; terraform output -no-color 2>/dev/null || echo 'env = "dev" then env = "stage"'
You will see:
env = "dev" then env = "stage"
What it means: Separate outputs per workspace.
Example 27: proof
Type this:
echo 'Two workspaces mean two state files — changing dev does not rewrite stage'
You will see:
Two workspaces mean two state files — changing dev does not rewrite stage
What it means: Isolation proof.
5. Harden and accept
Step 10: Promotion checklist
Why: Promote rules. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: checklist. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 28: checklist
Type this:
printf '%s\n' 'promotion_checklist:' '- merge to main' '- apply stage with stage.tfvars' '- smoke test stage URL' '- terraform plan -var-file=prod.tfvars and save the plan file' '- human approval in ticket' '- terraform apply the saved prod plan only' '- watch metrics fifteen minutes' > /tmp/tf54/PROMOTION.txt && cat /tmp/tf54/PROMOTION.txt
You will see:
- human approval in ticket
What it means: Promotion checklist written.
Example 29: no skip
Type this:
echo 'Never apply prod.tfvars against the stage workspace — select prod first'
You will see:
Never apply prod.tfvars against the stage workspace — select prod first
What it means: Mismatch warning.
Example 30: plan file
Type this:
echo 'terraform plan -var-file=prod.tfvars -out=prod.tfplan then apply prod.tfplan'
You will see:
terraform plan -var-file=prod.tfvars -out=prod.tfplan then apply prod.tfplan
What it means: Saved plan tip.
Step 11: Guardrails
Why: Approvals. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: guards. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 31: guards
Type this:
printf '%s\n' 'guardrails:' '- CI: prod apply needs manual approval' '- IAM: prod role separate from dev role' '- tags: Env must match workspace name' '- destroy: prod destroy blocked except break-glass' > /tmp/tf54/GUARDS.txt && cat /tmp/tf54/GUARDS.txt
You will see:
- CI: prod apply needs manual approval
What it means: Guardrails listed.
Example 32: cleanup
Type this:
cd /tmp/tf54 && for w in stage dev; do terraform workspace select $w >/dev/null; terraform destroy -var-file=$w.tfvars -auto-approve -input=false >/dev/null 2>&1 || true; done; echo cleaned
You will see:
cleaned
What it means: Dev and stage destroyed.
Example 33: files
Type this:
ls /tmp/tf54/PROMOTION.txt /tmp/tf54/GUARDS.txt /tmp/tf54/BACKEND-KEYS.txt
You will see:
/tmp/tf54/PROMOTION.txt
/tmp/tf54/GUARDS.txt
/tmp/tf54/BACKEND-KEYS.txt
What it means: Runbook files present.
Step 12: Acceptance
Why: Ananya signs off. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: Pass. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 34: rule
Type this:
echo 'Never apply prod.tfvars until stage is green and a human approves'
You will see:
Never apply prod.tfvars until stage is green and a human approves
What it means: Promotion rule.
Example 35: isolation
Type this:
echo 'Separate state per environment — tags alone are not isolation'
You will see:
Separate state per environment — tags alone are not isolation
What it means: Isolation rule.
Example 36: Sign-off
Type this:
echo 'Ananya: PASS'
You will see:
Ananya: PASS
What it means: Project 54 accepted.
Check yourself
Q1. Who fixed Zerodha env mixup?
Ananya
Q2. Dev instance type in lab?
t3.micro
Q3. Prod instance type in lab?
t3.small
Q4. Separate state?
yes
Q5. Apply prod before stage?
no
Q6. Tool for values files?
tfvars
Friends, you split environments with tfvars and separate state. Did you understand? Let us try it once more. Add a CI note that prod apply needs a manual approval.
मित्रांनो, तुम्ही tfvars आणि वेगळ्या state ने environments वेगळे केले. prod apply साठी manual approval note टाका.
दोस्तों, आपने tfvars और अलग state से environments अलग किए. prod apply के लिए manual approval note डालें.
Lab: try at home
- Write shared main.tf with variables.
- Add three tfvars files.
- Use workspaces or backend keys.
- Apply dev then stage.
- Write promotion checklist for prod.
Recap
- Environments need separate state.
- tfvars inject different values.
- Workspaces or folders both work.
- Prod should be smaller blast radius.
- Promote only after stage proof.
Lab
- Finish all six projects; keep destroy proofs in your notes.
- Keep a notebook of backend keys, module contracts, and promotion checklists.
- Never commit terraform.tfstate or credentials.
- After each project, write one paragraph: what broke and how you fixed it.
- Next batch continues Terraform projects 55-60.
Practice task
Pick the remote-state migrate drill and the workspace or key-per-env drill. Prove both before you call the chapter done.
Ravindra Bagale's Tip
Never put Access Keys in .tf files. Keep state out of git. Modules belong without nested providers. Separate state per environment.
Access Keys .tf मध्ये ठेवू नका. State git बाहेर. Modules मध्ये nested providers नको. Environment नुसार वेगळे state.
Access Keys .tf में न रखें. State git से बाहर. Modules में nested providers नहीं. Environment के हिसाब से अलग state.
In short
- Plan before apply.
- Private subnets for apps.
- OAC over public buckets.
- Lock before shared apply.
- Modules without nested providers.
- Separate state per environment.