Bicep Resources
The resource declaration is the core of every Bicep file. It tells Azure what to create, where to create it, and how to configure it. Everything covered so far — parameters, variables, and file structure — exists to support well-written resource declarations.
A resource in Bicep represents one Azure service: a storage account, virtual machine, web app, database, virtual network, or any of the hundreds of services available in Azure. Each resource gets its own declaration block in the Bicep file.
Resource Declaration Syntax
resource <symbolicName> '<ResourceType>@<ApiVersion>' = {
name: '<resourceName>'
location: '<region>'
<additional properties>
}
Breaking this down into its four parts:
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
│ │ │ │
│ │ │ └── API Version
│ │ └────────────────────────── Resource Type
│ └─────────────────────────────────────────────── Symbolic Name
└─────────────────────────────────────────────────────────── Keyword
| Part | Purpose | Rules |
|---|---|---|
| Symbolic Name | Refers to this resource elsewhere in the file | Unique within the file, camelCase recommended |
| Resource Type | Identifies which Azure service to create | Format: Provider/Type (case-sensitive) |
| API Version | Specifies which version of the Azure API to use | Date format YYYY-MM-DD, use latest stable |
| Properties Block | Configures the resource settings | Each resource type has different required/optional properties |
Common Azure Resource Types
| Azure Service | Resource Type |
|---|---|
| Storage Account | Microsoft.Storage/storageAccounts |
| Virtual Machine | Microsoft.Compute/virtualMachines |
| App Service Plan | Microsoft.Web/serverfarms |
| Web App | Microsoft.Web/sites |
| SQL Server | Microsoft.Sql/servers |
| SQL Database | Microsoft.Sql/servers/databases |
| Virtual Network | Microsoft.Network/virtualNetworks |
| Key Vault | Microsoft.KeyVault/vaults |
| Container Registry | Microsoft.ContainerRegistry/registries |
| Cosmos DB Account | Microsoft.DocumentDB/databaseAccounts |
Resource Properties
Every resource type has a set of required and optional properties. Required properties must always be present. Optional properties use Azure defaults when omitted.
Required Properties for Almost Every Resource
- name – The name of the resource in Azure. Must follow Azure naming rules for each service.
- location – The Azure region where the resource is created (e.g., 'eastus', 'westeurope').
Common Optional Properties
- tags – Key-value pairs for organizing and billing resources.
- sku – The pricing tier or performance level (e.g., 'Standard_LRS', 'B1').
- kind – A sub-type of the resource (e.g., 'StorageV2', 'FunctionApp').
- properties – Service-specific configuration settings.
- identity – Managed identity settings.
Example 1 – Storage Account
param location string = 'eastus'
param storageAccountName string = 'mystorage2024abc'
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
tags: {
environment: 'production'
}
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
supportsHttpsTrafficOnly: true
}
}
Example 2 – App Service Plan and Web App (Two Resources)
param location string = 'eastus'
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
name: 'asp-myapp'
location: location
sku: {
name: 'B1'
tier: 'Basic'
}
}
resource webApp 'Microsoft.Web/sites@2023-01-01' = {
name: 'app-myapp-prod'
location: location
kind: 'app'
properties: {
serverFarmId: appServicePlan.id
}
}
Notice that webApp references appServicePlan.id — the symbolic name followed by .id. This is how resources reference each other in Bicep without hardcoding IDs.
Resource Dependencies
Azure must create some resources before others. For example, a Web App cannot exist without an App Service Plan. Bicep detects dependencies automatically when one resource references another resource's property.
Automatic Dependency Detection
appServicePlan ──────────────────────────────────┐
(created first) │
▼
webApp uses: serverFarmId: appServicePlan.id webApp
(created after appServicePlan) (created second)
When Bicep sees appServicePlan.id inside the web app block, it knows to create the App Service Plan first. This implicit dependency is the recommended approach.
Explicit Dependencies with dependsOn
In rare cases where a resource needs to wait for another resource but does not directly reference it, use the dependsOn property.
resource scriptRunner 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
name: 'run-setup-script'
location: location
kind: 'AzureCLI'
dependsOn: [
storageAccount // wait for storage account before running script
]
properties: {
azCliVersion: '2.50.0'
scriptContent: 'echo "Setup complete"'
retentionInterval: 'PT1H'
}
}
Parent-Child Resources
Some Azure resources only exist inside another resource. A SQL Database lives inside a SQL Server. A Blob Container lives inside a Storage Account. These are called parent-child resource relationships.
Azure Resource Hierarchy Example SQL Server (Parent) │ ├── SQL Database 1 (Child) ├── SQL Database 2 (Child) └── SQL Database 3 (Child)
Method 1 – Using the parent Property (Recommended)
resource sqlServer 'Microsoft.Sql/servers@2023-08-01-preview' = {
name: 'sql-myapp'
location: location
properties: {
administratorLogin: 'sqladmin'
administratorLoginPassword: adminPassword
}
}
resource sqlDatabase 'Microsoft.Sql/servers/databases@2023-08-01-preview' = {
name: 'db-orders'
parent: sqlServer // links this database to the SQL server above
location: location
sku: {
name: 'Basic'
tier: 'Basic'
}
}
Method 2 – Nested Resource (Alternative)
resource sqlServer 'Microsoft.Sql/servers@2023-08-01-preview' = {
name: 'sql-myapp'
location: location
properties: {
administratorLogin: 'sqladmin'
administratorLoginPassword: adminPassword
}
// Database is nested directly inside the server block
resource sqlDatabase 'databases' = {
name: 'db-orders'
location: location
sku: {
name: 'Basic'
}
}
}
Managed Identity on Resources
Many Azure resources support Managed Identity — a way to authenticate to other Azure services without storing secrets. Assign a managed identity directly in the resource block:
resource webApp 'Microsoft.Web/sites@2023-01-01' = {
name: 'app-myapp-prod'
location: location
kind: 'app'
identity: {
type: 'SystemAssigned' // Azure creates and manages the identity
}
properties: {
serverFarmId: appServicePlan.id
}
}
Referencing Resource Properties
After declaring a resource, its properties become accessible throughout the file using the symbolic name followed by a dot and the property name.
// Access resource properties using the symbolic name storageAccount.id // Resource ID storageAccount.name // Resource name storageAccount.location // Location storageAccount.properties.primaryEndpoints.blob // Blob endpoint URL webApp.identity.principalId // Managed identity principal ID
Complete Example – Three Connected Resources
param location string = 'eastus'
param environment string = 'prod'
var prefix = 'myapp-${environment}'
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: 'st${replace(prefix, '-', '')}001'
location: location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
supportsHttpsTrafficOnly: true
}
}
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
name: 'asp-${prefix}'
location: location
sku: {
name: 'B1'
tier: 'Basic'
}
}
resource webApp 'Microsoft.Web/sites@2023-01-01' = {
name: 'app-${prefix}'
location: location
kind: 'app'
identity: {
type: 'SystemAssigned'
}
properties: {
serverFarmId: appServicePlan.id // implicit dependency
siteConfig: {
appSettings: [
{
name: 'STORAGE_ACCOUNT_NAME'
value: storageAccount.name
}
]
}
}
}
Summary
Resource declarations are the heart of Bicep. Every resource uses a symbolic name, a type string, an API version, and a properties block. Bicep detects dependencies automatically when resources reference each other. Parent-child relationships use the parent property or nested resource blocks. Resources expose their properties through their symbolic name, making it easy to connect related resources cleanly.
