<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: TechOpsBySonali</title>
    <description>The latest articles on Forem by TechOpsBySonali (@techopsbysonali).</description>
    <link>https://forem.com/techopsbysonali</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3589804%2Fa607c05d-6bd6-4893-9d47-9ffb54b855d5.png</url>
      <title>Forem: TechOpsBySonali</title>
      <link>https://forem.com/techopsbysonali</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/techopsbysonali"/>
    <language>en</language>
    <item>
      <title>🚀 Secrets Safe, 3-Tier Deployments Fast: Terraform + Azure Key Vault Complete Hands-On Guide</title>
      <dc:creator>TechOpsBySonali</dc:creator>
      <pubDate>Mon, 01 Dec 2025 10:40:33 +0000</pubDate>
      <link>https://forem.com/careerbytecode/secrets-safe-3-tier-deployments-fast-terraform-azure-key-vault-complete-hands-on-guide-4ml5</link>
      <guid>https://forem.com/careerbytecode/secrets-safe-3-tier-deployments-fast-terraform-azure-key-vault-complete-hands-on-guide-4ml5</guid>
      <description>&lt;p&gt;Deploying the same 3-tier application again and again — dev, test, prod — shouldn’t feel like déjà vu every time.&lt;br&gt;
But in many cloud teams, it &lt;em&gt;does&lt;/em&gt;.&lt;br&gt;
Manual fixes… copy-pasted Terraform… secrets hardcoded inside &lt;code&gt;.tfvars&lt;/code&gt;…&lt;br&gt;
One small change in dev, not updated in prod…&lt;br&gt;
&lt;strong&gt;Boom! Configuration drift, broken deployments, security risks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This hands-on guide shows you exactly how to eliminate all of that using:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Terraform Modular Architecture&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Azure Key Vault for Secure Secrets Management&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Remote State in Azure Storage&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;GitHub Actions for Fully Automated CI/CD&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By the end, you’ll be able to deploy dev, test, and prod environments &lt;strong&gt;identically&lt;/strong&gt;, &lt;strong&gt;securely&lt;/strong&gt;, and &lt;strong&gt;on autopilot&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔥 1. The Problem: Manual Deployments = Drift + Errors + Chaos
&lt;/h2&gt;

&lt;p&gt;Most teams still deploy environments like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy old Terraform folder&lt;/li&gt;
&lt;li&gt;Change a few names&lt;/li&gt;
&lt;li&gt;Adjust IPs manually&lt;/li&gt;
&lt;li&gt;Forget a network rule&lt;/li&gt;
&lt;li&gt;Hardcode passwords “for now” 😅&lt;/li&gt;
&lt;li&gt;Fix mistakes &lt;em&gt;after&lt;/em&gt; something breaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result?&lt;/p&gt;

&lt;p&gt;❌ Inconsistent infra across environments&lt;br&gt;
❌ Security breaches due to exposed secrets&lt;br&gt;
❌ Time wasted troubleshooting&lt;br&gt;
❌ Zero auditability&lt;br&gt;
❌ No single source of truth&lt;/p&gt;

&lt;p&gt;This hands-on solves exactly this.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚀 2. Why This Use Case Matters
&lt;/h2&gt;

&lt;p&gt;Cloud teams today need consistency + speed + security.&lt;br&gt;
Manually managing infra no longer works.&lt;/p&gt;

&lt;p&gt;This use case delivers:&lt;/p&gt;
&lt;h3&gt;
  
  
  🧱 &lt;strong&gt;Reusable Terraform Modules&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Resource Group, VNet, Subnet, NSG, VM — once written, reused forever.&lt;/p&gt;
&lt;h3&gt;
  
  
  🔐 &lt;strong&gt;Zero Secret Sprawl&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Passwords and sensitive values stored in Azure Key Vault, pulled directly in Terraform.&lt;/p&gt;
&lt;h3&gt;
  
  
  🚦 &lt;strong&gt;Environment-driven Deployment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;All differences (dev/test/prod) live in &lt;code&gt;terraform.tfvars&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  🤖 &lt;strong&gt;GitHub Actions = Fully Automated Deployments&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Plan → Validate → Apply → Audit logs — everything automated.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;production-grade Terraform&lt;/strong&gt;, not just a tutorial.&lt;/p&gt;


&lt;h2&gt;
  
  
  🕒 3. When You Need This Use Case
&lt;/h2&gt;

&lt;p&gt;You need this setup when:&lt;/p&gt;

&lt;p&gt;✔️ Deploying multiple environments&lt;br&gt;
✔️ Avoiding inconsistent infra&lt;br&gt;
✔️ Securing all secrets centrally&lt;br&gt;
✔️ Enabling fast onboarding&lt;br&gt;
✔️ Needing auditability and governance&lt;br&gt;
✔️ Running builds from CI/CD pipelines&lt;br&gt;
✔️ Scaling infra to multiple regions&lt;/p&gt;

&lt;p&gt;This architecture grows as your company grows.&lt;/p&gt;


&lt;h2&gt;
  
  
  🛠️ 4. Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Azure Subscription&lt;/li&gt;
&lt;li&gt;Azure CLI&lt;/li&gt;
&lt;li&gt;Terraform Installed&lt;/li&gt;
&lt;li&gt;Git + GitHub&lt;/li&gt;
&lt;li&gt;Key Vault access&lt;/li&gt;
&lt;li&gt;Optional: GitHub Actions Service Principal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’re ready.&lt;/p&gt;


&lt;h2&gt;
  
  
  🎯 5. Challenge Questions (Interview-Level)
&lt;/h2&gt;

&lt;p&gt;These make great &lt;strong&gt;DevOps interview&lt;/strong&gt; questions too:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How do you avoid copy-paste Terraform for dev/test/prod?&lt;/li&gt;
&lt;li&gt;How do you secure plaintext secrets in Terraform?&lt;/li&gt;
&lt;li&gt;How do you stop network drift between environments?&lt;/li&gt;
&lt;li&gt;How do you enable new developers to deploy infra securely?&lt;/li&gt;
&lt;li&gt;How do you prove that all environments are deployed from the same code?&lt;/li&gt;
&lt;li&gt;How do you roll back a Terraform deployment?&lt;/li&gt;
&lt;li&gt;How do you prevent faulty tfvars from affecting prod?&lt;/li&gt;
&lt;li&gt;How do you design a module for both Linux &amp;amp; Windows VMs?&lt;/li&gt;
&lt;li&gt;How do you deploy identical infra to two regions?&lt;/li&gt;
&lt;li&gt;Why are modules better than plain Terraform scripts?&lt;/li&gt;
&lt;/ol&gt;


&lt;h1&gt;
  
  
  🧑‍💻 6. Complete Hands-On Implementation
&lt;/h1&gt;

&lt;p&gt;Below is the &lt;strong&gt;full real-life end-to-end setup&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  STEP 1️⃣ — Authenticate to Azure &amp;amp; Configure Git
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az login
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"yourname"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"yourmail@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Initialize GitHub repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# azure-3-tier-architecture"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; README.md
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"first commit"&lt;/span&gt;
git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
git remote add origin https://github.com/&amp;lt;yourid&amp;gt;/azure-3-tier-architecture.git
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  STEP 2️⃣ — Create Backend Resources
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LOCATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"eastus"&lt;/span&gt;
&lt;span class="nv"&gt;RG_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"tfstate-rg"&lt;/span&gt;
&lt;span class="nv"&gt;STORAGE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mytfstate12345"&lt;/span&gt;
&lt;span class="nv"&gt;CONTAINER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"tfstate"&lt;/span&gt;
&lt;span class="nv"&gt;KV_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mykeyvault12345"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az group create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$RG_NAME&lt;/span&gt; &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nv"&gt;$LOCATION&lt;/span&gt;
az storage account create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$STORAGE_NAME&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$RG_NAME&lt;/span&gt; &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nv"&gt;$LOCATION&lt;/span&gt; &lt;span class="nt"&gt;--sku&lt;/span&gt; Standard_LRS
az storage container create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$CONTAINER_NAME&lt;/span&gt; &lt;span class="nt"&gt;--account-name&lt;/span&gt; &lt;span class="nv"&gt;$STORAGE_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  STEP 3️⃣ — Create Key Vault + Secrets
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az keyvault create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$KV_NAME&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$RG_NAME&lt;/span&gt; &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nv"&gt;$LOCATION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Store secrets
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az keyvault secret &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;--vault-name&lt;/span&gt; &lt;span class="nv"&gt;$KV_NAME&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"vm-username"&lt;/span&gt; &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"learning"&lt;/span&gt;
az keyvault secret &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;--vault-name&lt;/span&gt; &lt;span class="nv"&gt;$KV_NAME&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"vm-password"&lt;/span&gt; &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"Redhat@12345"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  STEP 4️⃣ — Create GitHub Service Principal
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az ad sp create-for-rbac &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"github-spn"&lt;/span&gt; &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Contributor"&lt;/span&gt; &lt;span class="nt"&gt;--scopes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/&amp;lt;subid&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;--sdk-auth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save JSON output.&lt;/p&gt;

&lt;p&gt;Grant Key Vault access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az role assignment create &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--assignee&lt;/span&gt; &amp;lt;clientId&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt; &lt;span class="s2"&gt;"Key Vault Secrets User"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--scope&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;az keyvault show &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$KV_NAME&lt;/span&gt; &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; tsv&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  STEP 5️⃣ — Create Terraform Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform/
├── backend.tf
├── main.tf
├── variables.tf
├── environments/
│   ├── dev/terraform.tfvars
│   ├── test/terraform.tfvars
│   └── prod/terraform.tfvars
└── modules/
    ├── rg/
    ├── vnet/
    ├── subnet/
    ├── nsg/
    └── vm/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  STEP 6️⃣ — Add Root Terraform Files
&lt;/h2&gt;

&lt;h3&gt;
  
  
  backend.tf
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tfstate-rg"&lt;/span&gt;
    &lt;span class="nx"&gt;storage_account_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mytfstate12345"&lt;/span&gt;
    &lt;span class="nx"&gt;container_name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tfstate"&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"3tier/dev.tfstate"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  variables.tf
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"location"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"rg_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"vnet_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"vm_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  main.tf
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;features&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"rg"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/rg"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg_name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"vnet"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/vnet"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vnet_name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"subnet"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/subnet"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.vnet_name}-subnet"&lt;/span&gt;
  &lt;span class="nx"&gt;vnet_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;nsg_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nsg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"nsg"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/nsg"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.vnet_name}-nsg"&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_key_vault"&lt;/span&gt; &lt;span class="s2"&gt;"kv"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mykeyvault12345"&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tfstate-rg"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_key_vault_secret"&lt;/span&gt; &lt;span class="s2"&gt;"vm_username"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vm-username"&lt;/span&gt;
  &lt;span class="nx"&gt;key_vault_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_key_vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_key_vault_secret"&lt;/span&gt; &lt;span class="s2"&gt;"vm_password"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vm-password"&lt;/span&gt;
  &lt;span class="nx"&gt;key_vault_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_key_vault&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"vm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/vm"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vm_name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_id&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;admin_username&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_key_vault_secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vm_username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
  &lt;span class="nx"&gt;admin_password&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_key_vault_secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vm_password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  STEP 7️⃣ — Environment Variables
&lt;/h2&gt;

&lt;h3&gt;
  
  
  dev
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;rg_name&lt;/span&gt;  &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rg-dev"&lt;/span&gt;
&lt;span class="nx"&gt;vnet_name&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vnet-dev"&lt;/span&gt;
&lt;span class="nx"&gt;vm_name&lt;/span&gt;   &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vm-dev"&lt;/span&gt;
&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eastus"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  STEP 8️⃣ — Build Modules
&lt;/h2&gt;

&lt;p&gt;(Example: Resource Group)&lt;/p&gt;

&lt;p&gt;modules/rg/main.tf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_resource_group"&lt;/span&gt; &lt;span class="s2"&gt;"rg"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;modules/rg/variables.tf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"location"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;modules/rg/outputs.tf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeat similar for vnet, subnet, nsg, vm.&lt;/p&gt;




&lt;h1&gt;
  
  
  🎉 Final Output
&lt;/h1&gt;

&lt;p&gt;You now have:&lt;/p&gt;

&lt;p&gt;✔️ Modular Terraform&lt;br&gt;
✔️ Secure secrets with Key Vault&lt;br&gt;
✔️ Remote state&lt;br&gt;
✔️ Reusable environments&lt;br&gt;
✔️ Ready for GitHub Actions automation&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;true enterprise-grade Infrastructure as Code&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⭐ Follow Me for Daily DevOps &amp;amp; Cloud Content
&lt;/h2&gt;

&lt;p&gt;🔵 LinkedIn: &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
🐦 Twitter / X: &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
📸 Instagram: &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
📝 Medium: &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
📚 Dev.to: &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
🌐 Hashnode: techopsbysonali.hashnode.dev&lt;br&gt;
🖋️ Blogger: techopsbysonali.blogspot.com&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;p&gt;📲 Join My WhatsApp Communities&lt;br&gt;
**&lt;br&gt;
👉 Personalized Guidance: &lt;a href="https://wa.me/7620774352" rel="noopener noreferrer"&gt;https://wa.me/7620774352&lt;/a&gt;&lt;br&gt;
👉 Latest Updates Group: &lt;a href="https://lnkd.in/gVTvmRBa" rel="noopener noreferrer"&gt;https://lnkd.in/gVTvmRBa&lt;/a&gt;&lt;br&gt;
👉 Pune Local Meetup Group: &lt;a href="https://lnkd.in/gQbKaUeX" rel="noopener noreferrer"&gt;https://lnkd.in/gQbKaUeX&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>azure</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Terraform Workspaces: Proven Multi-Environment Patterns for Real-World DevOps</title>
      <dc:creator>TechOpsBySonali</dc:creator>
      <pubDate>Sun, 23 Nov 2025 14:13:06 +0000</pubDate>
      <link>https://forem.com/careerbytecode/terraform-workspaces-proven-multi-environment-patterns-for-real-world-devops-1nme</link>
      <guid>https://forem.com/careerbytecode/terraform-workspaces-proven-multi-environment-patterns-for-real-world-devops-1nme</guid>
      <description>&lt;p&gt;&lt;strong&gt;Managing multiple environments (dev, staging, prod)&lt;/strong&gt; is a core requirement for any modern infrastructure setup. Terraform offers several ways to do this — but &lt;strong&gt;Terraform Workspaces&lt;/strong&gt; are often misunderstood, overused, or misused.&lt;/p&gt;

&lt;p&gt;This guide cuts through the noise with &lt;strong&gt;clear, real-world patterns&lt;/strong&gt; that developers can safely use in production-grade workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What Terraform Workspaces Actually Do&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Terraform Workspaces &lt;strong&gt;do NOT&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;❌ create separate directories&lt;br&gt;
❌ give you different pipelines&lt;br&gt;
❌ create different backend configurations&lt;/p&gt;

&lt;p&gt;They ONLY provide:&lt;/p&gt;

&lt;p&gt;✔ Separate &lt;strong&gt;state files&lt;/strong&gt; within the same backend&lt;br&gt;
✔ A way to reference the current workspace via &lt;code&gt;terraform.workspace&lt;/code&gt;&lt;br&gt;
✔ Simple environment switching from the CLI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform workspace new dev
terraform workspace new prod

terraform workspace &lt;span class="k"&gt;select &lt;/span&gt;dev
terraform workspace &lt;span class="k"&gt;select &lt;/span&gt;prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the workspace name in resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myapp-${terraform.workspace}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;myapp-dev&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;myapp-prod&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s all workspaces do — &lt;strong&gt;state separation + naming context&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;When You Should (and Should NOT) Use Workspaces&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✔ &lt;strong&gt;Use Workspaces When…&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Infra topology is identical across environments&lt;/li&gt;
&lt;li&gt;Your team has small/medium infrastructure&lt;/li&gt;
&lt;li&gt;You want simple state isolation&lt;/li&gt;
&lt;li&gt;You need quick environment testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✘ &lt;strong&gt;Avoid Workspaces When…&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Environments have &lt;strong&gt;different architectures&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You need &lt;strong&gt;different backends&lt;/strong&gt; per environment&lt;/li&gt;
&lt;li&gt;Every environment has its own repo&lt;/li&gt;
&lt;li&gt;Your CI/CD pipeline cannot safely switch workspaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When environments diverge significantly →&lt;br&gt;
&lt;strong&gt;Use folder-based or repo-based separation instead.&lt;/strong&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  &lt;strong&gt;Multi-Environment Patterns&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Below are practical Terraform patterns used by DevOps teams of all sizes.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Pattern 1: Simple Workspace-Based Environments&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A clean, minimal approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;infra/
  main.tf
  variables.tf
  outputs.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"region"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"web"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-123456"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t2.micro"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;terraform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform workspace new dev
terraform apply &lt;span class="nt"&gt;-var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"region=us-east-1"&lt;/span&gt;

terraform workspace new prod
terraform apply &lt;span class="nt"&gt;-var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"region=us-east-1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good for:&lt;/strong&gt;&lt;br&gt;
✔ Small projects&lt;br&gt;
✔ Simple infra&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitations:&lt;/strong&gt;&lt;br&gt;
✘ Doesn’t provide per-env backend security&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Pattern 2: Workspaces + Per-Environment Variable Files&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A scalable improvement over Pattern 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;infra/
  main.tf
  variables.tf
  env/
    dev.tfvars
    prod.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: &lt;code&gt;env/dev.tfvars&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;region&lt;/span&gt;        &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3.micro"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CI/CD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform workspace &lt;span class="k"&gt;select &lt;/span&gt;dev
terraform apply &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"env/dev.tfvars"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;br&gt;
✔ Separate configs&lt;br&gt;
✔ Same infra topology&lt;br&gt;
✔ Controlled differences&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Pattern 3: Workspaces with Dynamic Backends&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Store state in separate backend keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-terraform-states"&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"env/${terraform.workspace}/terraform.tfstate"&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resulting state files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env/dev/terraform.tfstate
env/prod/terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;br&gt;
✔ Strong isolation&lt;br&gt;
✔ Good for regulated industries&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;br&gt;
✘ Backend configs cannot always use variables&lt;br&gt;
✘ May require partial backend config overrides in CI/CD&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Pattern 4: Hybrid Model — Workspaces + Folder-Based Environments&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Perfect for mid-sized teams.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;infra/
  modules/
    network/
    compute/
  env/
    dev/
      main.tf
    prod/
      main.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: &lt;code&gt;env/dev/main.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../../modules/compute"&lt;/span&gt;
  &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;terraform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why teams love this pattern:&lt;/p&gt;

&lt;p&gt;✔ Versioned modules&lt;br&gt;
✔ Clean environment overrides&lt;br&gt;
✔ Workspace state isolation&lt;/p&gt;


&lt;h1&gt;
  
  
  &lt;strong&gt;Real-World Scenario Example&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;A microservices platform needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same infra topology across environments&lt;/li&gt;
&lt;li&gt;Different EC2 sizes for dev vs prod
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env/
  dev.tfvars
  prod.tfvars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;dev.tfvars&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;instance_type&lt;/span&gt;      &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3.micro"&lt;/span&gt;
&lt;span class="nx"&gt;enable_monitoring&lt;/span&gt;  &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;prod.tfvars&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;instance_type&lt;/span&gt;      &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"m5.large"&lt;/span&gt;
&lt;span class="nx"&gt;enable_monitoring&lt;/span&gt;  &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CI/CD deploy step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform workspace &lt;span class="k"&gt;select &lt;/span&gt;prod
terraform apply &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt;/prod.tfvars &lt;span class="nt"&gt;-auto-approve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outcome:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fully isolated state&lt;/li&gt;
&lt;li&gt;Clean promotions&lt;/li&gt;
&lt;li&gt;Parameterized infra&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Developer Tips&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;💡 &lt;strong&gt;Never store secrets in &lt;code&gt;.tfvars&lt;/code&gt;&lt;/strong&gt; → use Vault, SSM, or env variables.&lt;/p&gt;

&lt;p&gt;💡 Avoid switching workspaces inside long pipelines — risk of deploying to wrong environment.&lt;/p&gt;

&lt;p&gt;💡 Validate workspace names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;allowed&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"stage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"prod"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;is_valid&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;terraform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"null_resource"&lt;/span&gt; &lt;span class="s2"&gt;"validate"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;is_valid&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Use workspaces &lt;strong&gt;only when architecture remains consistent&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Common Questions Developers Ask&lt;/strong&gt;
&lt;/h1&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Are workspaces the same as Git branches?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;No. Workspaces only isolate terraform &lt;strong&gt;state&lt;/strong&gt;, not code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Should I use workspaces for production?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✔ Yes — if infra is identical&lt;br&gt;
✘ No — if prod requires unique architecture&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;3. Do workspaces isolate backend buckets?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Only if you configure the backend key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"env/${terraform.workspace}/terraform.tfstate"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;4. Should each environment have its own workspace or folder?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;workspaces&lt;/strong&gt; → simple infra&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;folders/repos&lt;/strong&gt; → complex infra&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Do workspaces prevent mistakes?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;They avoid state overlap but do &lt;strong&gt;not&lt;/strong&gt; protect against bad pipelines.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Related Tools &amp;amp; Ecosystem&lt;/strong&gt;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terragrunt&lt;/strong&gt; — advanced multi-env orchestration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atlantis&lt;/strong&gt; — Terraform GitOps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spacelift / Terraform Cloud&lt;/strong&gt; — remote runs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tflint / tfsec / Terrascan&lt;/strong&gt; — linting &amp;amp; security&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infracost&lt;/strong&gt; — cost analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-commit Terraform Hooks&lt;/strong&gt; — automatic linting&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Terraform Workspaces are powerful when used correctly.&lt;br&gt;
They shine when your environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;share the same architecture&lt;/li&gt;
&lt;li&gt;need simple state isolation&lt;/li&gt;
&lt;li&gt;require parametrized differences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use these patterns to structure your environments safely and avoid the common pitfalls most teams fall into.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⭐ Follow Me for Daily DevOps &amp;amp; Cloud Content
&lt;/h1&gt;

&lt;p&gt;🔵 &lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
🐦 &lt;strong&gt;Twitter / X:&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
📸 &lt;strong&gt;Instagram:&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
📝 &lt;strong&gt;Medium:&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
📚 &lt;strong&gt;Dev.to:&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/techopsbysonali"&gt;@techopsbysonali&lt;/a&gt;&lt;br&gt;
🌐 &lt;strong&gt;Hashnode:&lt;/strong&gt; techopsbysonali.hashnode.dev&lt;br&gt;
🖋️ &lt;strong&gt;Blogger:&lt;/strong&gt; techopsbysonali.blogspot.com&lt;/p&gt;




&lt;h1&gt;
  
  
  📲 Join My WhatsApp Communities
&lt;/h1&gt;

&lt;p&gt;👉 Personalized Guidance: &lt;a href="https://wa.me/7620774352" rel="noopener noreferrer"&gt;https://wa.me/7620774352&lt;/a&gt;&lt;br&gt;
👉 Latest Updates Group: &lt;a href="https://lnkd.in/gVTvmRBa" rel="noopener noreferrer"&gt;https://lnkd.in/gVTvmRBa&lt;/a&gt;&lt;br&gt;
👉 Pune Local Meetup Group: &lt;a href="https://lnkd.in/gQbKaUeX" rel="noopener noreferrer"&gt;https://lnkd.in/gQbKaUeX&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fec0iep0q19cxemh377gw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fec0iep0q19cxemh377gw.jpg" alt=" " width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>cloud</category>
      <category>devops</category>
      <category>interview</category>
    </item>
  </channel>
</rss>
