CtrlK
BlogDocsLog inGet started
Tessl Logo

azure-bicep-patterns

**UTILITY SKILL** — Reusable Azure Bicep patterns: hub-spoke, private endpoints, diagnostics, AVM composition. WHEN: "hub-spoke Bicep", "private endpoint module", "diagnostic settings", "AVM Bicep composition". USE FOR: Bicep template design, hub-spoke networking, private endpoint patterns, AVM modules. DO NOT USE FOR: Terraform code (use terraform-patterns), architecture decisions (use azure-adr), troubleshooting, diagram generation (use drawio).

75

Quality

92%

Does it follow best practices?

Impact

No eval scenarios have been run

SecuritybySnyk

Advisory

Suggest reviewing before use

SKILL.md
Quality
Evals
Security

Azure Bicep Patterns Skill

Reusable infrastructure patterns for Azure Bicep templates. Complements iac-bicep-best-practices.instructions.md (style) and azure-defaults skill (naming, tags, regions).

Canonical sources — the security baseline, AVM-first mandate, naming conventions, required tags, and unique-suffix rule live in azure-defaults/SKILL.md and iac-policy-compliance.md. This skill restates the rules tersely below for IaC-output convenience only; in conflict, the canonical sources win.

Quick Reference

PatternWhen to UseReference
Hub-Spoke NetworkingMulti-workload environments with shared serviceshub-spoke-pattern
Private Endpoint WiringAny PaaS service requiring private connectivityprivate-endpoint-pattern
Diagnostic SettingsEvery deployed resource (mandatory)common-patterns
Conditional DeploymentOptional resources controlled by parameterscommon-patterns
Module CompositionBreaking main.bicep into reusable modulescommon-patterns
Managed Identity BindingAny service-to-service authenticationcommon-patterns
Budget & Cost MonitoringEvery deployment (mandatory)budget-pattern
What-If / AVM PitfallsPre-deployment validation & AVM gotchasavm-pitfalls
Batch Bicep FormattingAfter generating/editing the Bicep treenpm run format:bicep -- infra/bicep/{project} (wraps bicep format)

Canonical Example — Module Interface

Every Bicep module in this repo follows the same input/output contract:

  • Inputs (required): name, location, tags, logAnalyticsWorkspaceName
  • Outputs (required): resourceId, resourceName, principalId (use .?principalId ?? '' so modules without managed identity still expose the output)

Full code sample and rationale: references/module-interface.md.

Steps

Applying a pattern in a Bicep template:

  1. Identify the pattern — match your need to a row in Quick Reference (hub-spoke, private endpoint, diagnostics, conditional, identity, budget)
  2. Load the reference — read the linked references/*.md for the chosen pattern; do not load all at once
  3. Compose the module — follow the Module Interface contract above (name/location/tags/logAnalyticsWorkspaceName in; resourceId/resourceName/principalId out)
  4. Pin AVM versions to the latest stable — at plan time, query MCR (https://mcr.microsoft.com/v2/bicep/avm/res/{path}/tags/list) and pin the highest non-prerelease semver; never reuse a version from training data, a prior project, or references/avm-modules.md. Stale pins require a pin_policy.mode = "exception" block in 04-iac-contract.json (see azure-defaults skill). Enforced by npm run validate:avm-versions:freeze.
  5. Add diagnostics + budget — every deployed resource gets a diagnostic setting; every deployment gets a budget with 80%/100%/120% forecast alerts
  6. What-if before deploy — run az deployment group what-if and review for unexpected deletes, SKU downgrades, or auth changes
  7. Validatebicep build + bicep lint + npm run validate:iac-security-baseline

Rules

  • Hub-Spoke: Hub holds shared infra; spokes peer to hub only; NSGs per subnet
  • Private Endpoints: Always wire PE + DNS Zone Group + DNS Zone; see group ID table in reference
  • Diagnostics: categoryGroup: 'allLogs' + AllMetrics; pass workspace name not ID
  • Conditional: bool params with defaults; guard outputs with ternary
  • Identity: guid() for idempotent role names; principalType: 'ServicePrincipal'; scope narrowly
  • Budget: 3 forecast thresholds (80%/100%/120%); amount and emails MUST be parameters
  • What-If: Run before every deploy; watch for unexpected deletes and SKU downgrades
  • AVM: ALWAYS pin to the latest published stable version (resolve at plan time via MCR tags/list); wrap modules to override defaults; verify outputs in README. Stale pins require a pin_policy exception block — see azure-defaults skill.
  • AVM Version Source of Truth: MCR tag listing (mcr.microsoft.com/v2/bicep/{module}/tags/list) is authoritative. Helpers and doc tables are NOT — they go stale. Validator: npm run validate:avm-versions.

Gotchas

  • AVM output shapes vary across modules — Different AVM modules expose different outputs. Always check the module README before referencing outputs.
  • Tag merging in AVM modules — Some AVM modules merge tags internally. Verify deployed tags include all required policy tags after deployment.
  • What-If red flags — Watch for unexpected deletes, SKU downgrades, public access changes, authentication mode changes, or identity removal. Always run what-if before deploy.
  • MCR version discovery — When AVM version helpers are incomplete, query mcr.microsoft.com/v2/bicep/{module}/tags/list for authoritative published versions.
  • Cross-RG module scope: ARM ID split indexes — Splitting a full resource ID (/subscriptions/{sub}/resourceGroups/{rg}/providers/...) on / yields ['', 'subscriptions', '{sub}', 'resourceGroups', '{rg}', ...]. Subscription is at index 2, RG name is at index 4. Use: scope: resourceGroup(split(resId, '/')[2], split(resId, '/')[4]). Indexes [1]/[3] are the literals 'subscriptions'/'resourceGroups' and only fail at az deployment ... validate time.
  • AVM insights/metric-alert:0.4.1+ requires criteria.allof[].name — Each entry in criteria.allOf[] needs a name field; omission passes bicep build but fails az deployment ... validate:
    allOf: [{
      name: 'HighCpu'        // REQUIRED
      metricName: 'Percentage CPU'
      operator: 'GreaterThan'
      threshold: 80
      timeAggregation: 'Average'
    }]
  • bicep build poisons tree-hash folders — Running bicep build main.bicep emits main.json next to the source. If the folder is hashed by validate-iac-handoff.mjs, that compiled output drifts the hash. The validator now excludes <stem>.json siblings of <stem>.bicep, but if you must build manually inside a handoff tree, rm -f main.json immediately after.

Reference Index

FileContent
hub-spoke-pattern.mdHub-spoke VNet orchestration with peering
private-endpoint-pattern.mdPE wiring + DNS zone groups + group ID table
common-patterns.mdDiagnostics, conditional deploy, module composition, managed identity
budget-pattern.mdConsumption budget, forecast alerts, anomaly detection
avm-pitfalls.mdWhat-if interpretation, AVM gotchas, learn more links
module-interface.mdCanonical module input/output contract

Learn More

TopicHow to Find
AVM module catalogmcp_azure-mcp_documentationcommand: "microsoft_docs_search", query: "Azure Verified Modules registry Bicep"
Resource type schemamcp_azure-mcp_documentationcommand: "microsoft_docs_search", query: "{resource-type} Bicep template reference"
Repository
jonathan-vella/azure-agentic-infraops
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.