---
applyTo: "**/*.bicep,**/*.bicepparam,**/bicepconfig.json"
description: Azure Bicep infrastructure conventions
---

# Azure Bicep

## Workflow
- Validate with `az bicep build --file main.bicep` (runs the linter) and preview with `az deployment group what-if` (or `sub`/`mg` scope) before any deploy. Never run `az deployment ... create` unless asked; deployments go through CI.
- Linter rules live in `bicepconfig.json`; fix warnings rather than disabling them.

## Structure
- `main.bicep` orchestrates; reusable pieces are modules in `modules/`. Prefer Azure Verified Modules (`br/public:avm/...`) with pinned versions over hand-written equivalents.
- One `.bicepparam` file per environment (`dev.bicepparam`, `prod.bicepparam`) using `using './main.bicep'`. No environment `if` ladders inside templates.
- Pin resource API versions explicitly and update them deliberately.
- Reference resources you don't own with the `existing` keyword instead of redeclaring them.

## Parameters and outputs
- Every parameter has a type, `@description`, and constraints (`@allowed`, `@minLength`, `@maxLength`). Use user-defined types for structured objects.
- Secrets are `@secure()` parameters or Key Vault references (`getSecret()` in param files). Never output secrets, keys or connection strings.
- Derive names from a prefix/environment/location pattern with `uniqueString(resourceGroup().id)` where global uniqueness is needed; keep naming in one place.

## Security defaults
- Managed identities with role assignments (`Microsoft.Authorization/roleAssignments` scoped to the resource, `guid()` names) instead of access keys.
- Disable public network access and enable HTTPS-only/TLS 1.2+ where the resource supports it; diagnostics to Log Analytics.
- Apply required tags from a shared `tags` parameter to every resource.

## Done when
Build/lint is clean and the what-if output was reviewed for unexpected deletes or replacements; mention any resource that will be recreated.
