Provision Microsoft Fabric with Azure Bicep

Overview

Microsoft Fabric consolidates analytics workloads (including Power BI) on a tenant-wide capacity. These Fabric capacities (SKUs F2–F2048) can be provisioned declaratively with Bicep like any other Azure resource. This post covers:

  • Prerequisites and quotas
  • A minimal Bicep template for Microsoft.Fabric/capacities@2023-11-01
  • An alternative using Azure Verified Modules (AVM)
  • Deployment via Azure CLI (including what-if)
  • Common errors and tips

Note: Power BI Premium P-SKUs support Fabric, but the modern Azure resource for IaC is Microsoft.Fabric/capacities.

Prerequisites

  • Azure subscription with sufficient Fabric quota (Capacity Units, CU)
  • Resource provider registered: Microsoft.Fabric
  • Permissions: at least Contributor on the resource group and deployment permissions (Microsoft.Resources/deployments/*)
  • Region where Fabric is available
  • Email addresses of capacity administrators (Microsoft Entra accounts)

Recommended checks/steps:

  1. Register the resource provider (one-time):
1az provider register --namespace Microsoft.Fabric
2az provider show -n Microsoft.Fabric --query registrationState -o tsv
  1. Check/raise quota (Portal: Quotas > Microsoft Fabric). API: REST Fabric Capacities - List Usages (2023-11-01).

Minimal: Fabric capacity with Bicep

The following Bicep file creates a Fabric capacity with configurable SKU, region, tags, and administrators. Key points:

  • Type: Microsoft.Fabric/capacities@2023-11-01
  • sku: name (e.g., F2, F4, F8 …) and tier = Fabric
  • properties.administration.members: list of admin email addresses
  • Naming rules for capacityName: 3–63 characters, only lowercase a–z and 0–9, must start with a letter.
 1// main.bicep
 2targetScope = 'resourceGroup'
 3
 4@description('Name of the Fabric capacity (3–63 chars, lowercase a–z and 0–9 only, start with a letter)')
 5@minLength(3)
 6@maxLength(63)
 7param capacityName string
 8
 9@description('Azure region for the capacity')
10param location string = resourceGroup().location
11
12@description('Fabric SKU (F2, F4, F8, F16, F32, F64, F128, F256, F512, F1024, F2048)')
13@allowed(['F2','F4','F8','F16','F32','F64','F128','F256','F512','F1024','F2048'])
14param skuName string = 'F2'
15
16@description('Email addresses of capacity administrators (Microsoft Entra IDs)')
17param adminMembers array
18
19@description('Optional tags')
20param tags object = {}
21
22resource capacity 'Microsoft.Fabric/capacities@2023-11-01' = {
23	name: capacityName
24	location: location
25	tags: tags
26	sku: {
27		name: skuName
28		tier: 'Fabric'
29	}
30	properties: {
31		administration: {
32			members: adminMembers
33		}
34	}
35}
36
37output capacityId string = capacity.id

Example Bicep parameters file (.bicepparam):

 1// parameters.dev.bicepparam
 2using './main.bicep'
 3
 4param capacityName = 'fabricdev001'
 5param location = 'westeurope'
 6param skuName = 'F2'
 7param adminMembers = [
 8	'admin@benjamin-abt.com'
 9	'support@benjamin-abt.com'
10]
11param tags = {
12	env: 'dev'
13	owner: 'data-platform'
14}

Alternative: Use the AVM module (best practice)

Instead of defining the resource type directly, you can use the Azure Verified Module (AVM). The module encapsulates best practices (e.g., lock options) and is versioned.

 1// main.bicep (AVM)
 2module fabricCapacity 'br/public:avm/res/fabric/capacity:<version>' = {
 3	name: 'fabricCapacity'
 4	params: {
 5		name: 'fabricdev001'
 6		adminMembers: [ 'admin@benjamin-abt.com', 'support@benjamin-abt.com' ]
 7		location: resourceGroup().location
 8		// Optional:
 9		// skuName: 'F64'
10		// tags: { env: 'dev' }
11		// lock: { kind: 'CanNotDelete', name: 'protect-fabric' }
12	}
13}

See the module reference and allowed values: br/public:avm/res/fabric/capacity (API version 2023-11-01).

Deploy with Azure CLI (PowerShell)

Deploy to a resource group using what-if followed by create:

 1# Variables
 2$rg = "rg-fabric-dev"
 3$loc = "westeurope"
 4
 5# Ensure resource group
 6az group create --name $rg --location $loc | Out-Null
 7
 8# What-if (dry run)
 9az deployment group what-if `
10	--resource-group $rg `
11	--name fabricWhatIf `
12	--template-file ./main.bicep `
13	--parameters @./parameters.dev.bicepparam
14
15# Deploy
16az deployment group create `
17	--resource-group $rg `
18	--name fabricDeploy `
19	--template-file ./main.bicep `
20	--parameters @./parameters.dev.bicepparam

Optionally separate environments/subscriptions with multiple parameter files (parameters.dev.bicepparam, parameters.prod.bicepparam) and tags.

Common errors & fixes

  • ProviderNotRegistered: Microsoft.Fabric isn’t registered. Fix: az provider register --namespace Microsoft.Fabric and wait for Registered.
  • QuotaExceeded / Quota = 0: No or insufficient Fabric quota in the subscription. Increase under “Quotas > Microsoft Fabric” in the Azure portal.
  • InvalidSku: SKU not available or typo. Allowed values: F2, F4, F8, … F2048 (and region-dependent availability).
  • Invalid adminMembers: Only valid Microsoft Entra accounts as emails.
  • Unsupported region: Ensure the region supports Fabric for your subscription.
  • “All provided principals must be existing, user or service principals”: This often happens when adminMembers contains GUID object IDs or non-email identifiers. Use user principal names (email addresses), e.g., admin@benjamin-abt.com. Ensure those users exist in your tenant. Do not pass object IDs here.

Security & governance

  • RBAC: Deploy via Service Principal (CI/CD) with least privilege (Contributor on RG). Manage capacity admins separately via adminMembers.
  • Tags & naming: Consistent conventions, tags for cost center/environment.
  • Locks: Protect from accidental deletion with resource locks (CanNotDelete).

Further reading

Happy automating!


Comments

Twitter Facebook LinkedIn WhatsApp