Note 20 · Azure (1/2)

Env Isolation: How Do You Handle Dev/Staging/Prod with Azure CLI and Subscriptions?

Show how collapsing redundant env templates and treating Azure CLI subscriptions/resource groups as the real isolation boundary prevents POC/MVP config drift.

2 September 2026 9 min read

Key takeaways

  • Treat Azure CLI subscription, resource group, and identity as the isolation boundary.
  • Keep a canonical env template set in Git; delete near-duplicate examples.
  • Secrets live in Key Vault / App Settings; templates document names only.
  • Deploy scripts print and verify az account show and target RG before mutate.
  • Share product code across POC/MVP; keep separate resource groups and stage settings.
  • One path map for humans and agents; fail closed when required settings are missing.

Six nearly identical .env.example files feel thorough. They guarantee drift. Someone updates three. Prod still reads the fourth. Agents and humans resolve different paths. The repo looks configured. The cloud is the actual environment, and nobody agrees which subscription is live.

Treat Azure CLI context (subscription, resource group, identity) as the isolation boundary. Keep a small set of live env files plus stage templates that document names, not secrets. POC and MVP can share product code while keeping separate deploy stages.

Named model: files describe; CLI selects

  • Template set: canonical stage templates in Git document setting names and non-secret defaults. One path map. No sixth clone.
  • Secrets store: Key Vault references and App Settings hold values. Templates never embed connection strings.
  • CLI context: subscription, resource group, and deploy identity select where changes land. Print and verify before mutate.
  • Contract: a correct .env against the wrong subscription is a successful deployment to the wrong world.

Named model: template set describes shape, secrets store holds values, Azure CLI context selects the real environment

Figure 1. Files describe configuration shape. Azure CLI context selects the real environment. Right file plus wrong subscription is still a wrong-world success.

Context and constraint

A common failure: dotenv archaeology outgrows the feature work. Local runs work. Slot swaps fail. The bug is not Node. It is four templates telling four slightly different truths about the same Key Vault name.

Application secrets belong in Key Vault and App Settings. Templates only document names and non-secret defaults. Collapsing redundant examples reduces the places drift can hide. Humans and coding agents should resolve paths from one documented source of truth, not from whichever folder they opened first.

Figure 2 is the Learn surface for cloud isolation posture. Subscription, resource group, identity, and network boundaries are the real walls. Env files only name what those walls should hold.

Private Link PaaS workflow diagram

Figure 2. Cloud isolation is subscription, resource group, identity, and network posture. Env files only describe names. Source: Microsoft Learn: overview.

Figure 3 is why stage isolation is a deploy concern. POC and MVP can share product code while keeping separate deploy stages and Azure CLI contexts.

App Service deployment slot flow diagram

Figure 3. POC and MVP can share product code while keeping separate deploy stages and Azure CLI contexts. Source: Microsoft Learn: App Service deploy best practices.

Design

1. Two live files, stage templates, not six clones

Keep a minimal local override pattern and explicit stage templates (for example POC and MVP, or Test and Prod). Delete near-duplicate examples that differ by one hostname. If a value is stage-specific, it belongs in a stage template or in Azure, not in a sixth "example-final-final" file. Figure 4 is the sprawl you delete versus the set you keep.

Anti-pattern of six drifting env examples versus a canonical live override, stage templates, and Azure targets documented once

Figure 4. Template set, not six clones. When someone proposes a seventh example, ask which of the six already lied.

2. Names in Git, secrets in Azure

Templates list setting names and point to Key Vault references or App Settings. They do not embed connection strings. Reviewers should reject secret material in env examples the same way they reject committed credentials. Documentation of names is enough for onboarding.

3. Azure CLI context is the environment switch

Subscription, resource group, and the identity you deploy as define where changes land. A correct .env against the wrong subscription is a successful deployment to the wrong world. Scripts should print and verify az account show and target RG before apply. Make context visible in CI logs. Figure 5 is the gate before mutate.

Deploy flow: accept stage, resolve template, print and verify az account show and target RG, then apply

Figure 5. Verify subscription and resource group before mutate. Visibility in the log beats tribal memory after a noisy afternoon.

4. Shared product code, separate deploy stages

POC and MVP can share the application. They should not share resource groups, app registrations without intent, or "temporary" settings that became permanent. Stage isolation is a deploy concern. Code forks for env isolation are usually a mistake.

5. One path resolution story for humans and agents

Document canonical paths for templates, local overrides, and deploy parameter files. Coding agents that invent a third env location will recreate drift at machine speed. Put the map in README or a short ops doc next to the templates.

6. Fail closed on missing required names

Startup or deploy checks should fail when required App Settings are absent, not silently fall back to a neighbor stage's values. Friendly defaults that reach the wrong store are hostile in production.

Agents make drift louder

Coding agents will happily create .env.local2 and hard-code a resource group they saw in an old transcript. Constrain them with the same path map humans use. Prefer scripts that accept --stage and resolve everything else from documented templates plus Azure CLI context. If an agent can invent a new env dialect in one session, your isolation model was already too fuzzy for humans.

A minimal template layout that survives contact

One README section names the live override file, the stage templates, and the Azure targets those templates describe. Deploy scripts read stage as an argument, set subscription and resource group explicitly, then apply. Local developers copy a template once and keep secrets out of Git. When someone proposes a seventh example file, ask which of the six already lied. Usually the answer is "more than one."

Print the resolved subscription id and resource group at the start of every deploy log line humans read. Visibility beats tribal memory when someone asks "which env did we just touch?" after a noisy afternoon.

Stage names in scripts should match stage names in Azure resource groups closely enough that a stranger can map them without a decoder ring.

Failure modes

Template sprawl. Six examples, four stale, two wrong.

Secrets in Git "just for local." They leak. Rotate forever.

Right file, wrong subscription. Green deploy, wrong blast radius.

POC settings copied into MVP by habit. Networking and identity assumptions travel unpaid.

Agent-invented env paths. Automation amplifies folklore.

Silent fallbacks across stages. Wrong Key Vault, correct HTTP 200.

What to copy / what not to copy

Copy

  • Canonical env template set (count and names) checked into Git.
  • Secrets only in Key Vault / App Settings; templates document names.
  • Deploy scripts verify Azure CLI subscription and RG before mutate.
  • POC and MVP (or Test/Prod) use separate resource groups and stage settings.
  • Single documented path map for humans and agents.
  • Startup/deploy fails if required settings are missing.

Do not copy blindly

Fewer templates means less copy-paste onboarding and more reliance on Azure portal or CLI literacy. That is the correct skill for cloud apps. Strict context checks add a few seconds to scripts and prevent week-long misdeploy stories. Shared code across stages requires discipline in feature flags and setting names; the alternative is divergent forks that never merge. Key Vault references add moving parts. They beat plaintext env files in repos.

Primary references: Microsoft Learn on Azure CLI configuration, App Service app settings, and Key Vault references.

Isolate with Azure CLI discipline, shrink the template set, keep secrets in Azure, and make context impossible to ignore. Drift shrinks when the cloud boundary is the boundary you actually use.