Bicep Variables
Variables in Bicep store calculated or composed values that the template uses internally. A variable cannot receive input from outside — it is always computed from other values already available in the file. Variables reduce repetition, improve readability, and make complex expressions easier to maintain.
Think of a variable like a sticky note. Instead of writing a long calculation on every page of a document, write it once on a sticky note and reference that note wherever needed. Change the sticky note once, and every reference updates automatically.
Parameters vs Variables – The Key Difference
+-----------------------------------------------------+ | Parameters vs Variables | +--------------+-------------------------------------+ | Feature | param | var | +--------------+-----------------+-------------------+ | Input | From outside | Inside file only | | (at deploy) | (user/pipeline)| (computed) | +--------------+-----------------+-------------------+ | Purpose | Customization | Reuse & clarity | +--------------+-----------------+-------------------+ | Changeable | Yes, per | No, fixed at | | at deploy | deployment | file level | +--------------+-----------------+-------------------+ | Default | Optional | Always required | | value | | | +--------------+-----------------+-------------------+
Basic Variable Syntax
var <variableName> = <value or expression>
Variable declarations use the var keyword followed by a name, an equals sign, and a value. No data type is declared — Bicep infers the type from the value automatically.
var prefix = 'myapp' var environment = 'prod' var instanceCount = 3 var enableLogs = true
String Interpolation in Variables
String interpolation combines string text with variable or parameter values using the ${} syntax. This is the most common reason to use variables — building resource names from multiple parts.
param environment string = 'prod'
param appName string = 'orderservice'
// Build a consistent naming pattern
var storageName = 'st${appName}${environment}'
var appServiceName = 'app-${appName}-${environment}'
var keyVaultName = 'kv-${appName}-${environment}'
When environment = 'prod' and appName = 'orderservice', the variables produce:
storageName = 'storderserviceprod' appServiceName = 'app-orderservice-prod' keyVaultName = 'kv-orderservice-prod'
Variables with Built-in Functions
Variables become powerful when combined with Bicep's built-in functions. One of the most common use cases is generating unique resource names using uniqueString().
// uniqueString generates a 13-character hash from the resource group ID
// The hash is the same every time for the same resource group
var uniqueSuffix = uniqueString(resourceGroup().id)
// Combine with a prefix to create a unique storage account name
var storageAccountName = 'storage${uniqueSuffix}'
The uniqueString() function produces the same result every time it runs against the same resource group. This means re-deploying the template always produces the same name — no duplicate resources are created accidentally.
Object Variables
Variables can store entire objects. This is especially useful for tags, configuration blocks, and settings that appear across multiple resources.
param environment string = 'production'
param project string = 'e-commerce'
// Define tags once as a variable
var commonTags = {
environment: environment
project: project
managedBy: 'Bicep'
costCenter: 'IT-001'
}
// Apply the same tags to multiple resources
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: 'mystorage001'
location: 'eastus'
tags: commonTags // reuse variable here
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
}
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
name: 'my-app-plan'
location: 'eastus'
tags: commonTags // same variable reused here
sku: {
name: 'B1'
}
}
Without the commonTags variable, the same tag object would need to be written inside every resource block. Changing a tag value would require editing every resource individually — a maintenance risk.
Array Variables
// List of allowed IP addresses for a firewall rule var allowedIpAddresses = [ '203.0.113.10' '198.51.100.25' '192.0.2.100' ] // List of subnet names var subnetNames = [ 'frontend-subnet' 'backend-subnet' 'database-subnet' ]
Variables That Reference Other Variables
Variables can build on each other. Later variables can reference earlier variables in the same file.
param appName string = 'webapp'
param environment string = 'dev'
// Base naming prefix
var namingPrefix = '${appName}-${environment}'
// Resources named using the prefix variable
var storageNameFull = 'st${replace(namingPrefix, '-', '')}001'
var appServiceNameFull = 'app-${namingPrefix}'
var keyVaultNameFull = 'kv-${namingPrefix}'
Conditional Variable Values
A variable can take different values based on a condition using the ternary operator (condition ? valueIfTrue : valueIfFalse).
param environment string = 'prod' // Choose the SKU based on environment var storageSku = environment == 'prod' ? 'Standard_GRS' : 'Standard_LRS' // Choose instance count based on environment var instanceCount = environment == 'prod' ? 3 : 1 // Choose whether HTTPS is enforced var httpsOnly = environment == 'prod' ? true : false
Logic Diagram – Conditional Variable
environment == 'prod'?
│
┌────┴────┐
YES NO
│ │
Standard Standard
_GRS _LRS
Complete Example – Variables in a Real Template
// Parameters
param location string = 'eastus'
param appName string = 'inventoryapp'
param environment string = 'staging'
// Variables
var namingPrefix = '${appName}-${environment}'
var uniqueSuffix = uniqueString(resourceGroup().id)
var storageAccountName = 'st${replace(namingPrefix, '-', '')}${take(uniqueSuffix, 4)}'
var appServicePlanName = 'asp-${namingPrefix}'
var webAppName = 'app-${namingPrefix}'
var storageSku = environment == 'prod' ? 'Standard_GRS' : 'Standard_LRS'
var commonTags = {
application: appName
environment: environment
managedBy: 'Bicep'
}
// Resources using variables
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
tags: commonTags
sku: {
name: storageSku
}
kind: 'StorageV2'
}
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
name: appServicePlanName
location: location
tags: commonTags
sku: {
name: 'B1'
}
}
resource webApp 'Microsoft.Web/sites@2023-01-01' = {
name: webAppName
location: location
tags: commonTags
kind: 'app'
properties: {
serverFarmId: appServicePlan.id
}
}
Naming Rules for Variables
| Rule | Correct Example | Incorrect Example |
|---|---|---|
| Start with a letter or underscore | var appName, var _config | var 1appName |
| Use camelCase for readability | var storageAccountName | var storageaccountname |
| No spaces in name | var namingPrefix | var naming prefix |
| No Bicep keywords as names | var resourceName | var resource |
| Descriptive names | var storageAccountName | var x, var temp |
When to Use Variables vs Parameters
Decision Guide
──────────────
Does the value change between deployments?
│
├── YES ──► Use a PARAMETER
│ (e.g., environment name, location, SKU)
│
└── NO ───► Is the value calculated from other values?
│
├── YES ──► Use a VARIABLE
│ (e.g., resource names, tags, derived config)
│
└── NO ────► Use a LITERAL directly in the resource block
(e.g., a fixed API version, a constant kind)
Summary
Variables in Bicep store computed values that the template uses internally. They reduce repetition, enforce consistent naming, and make templates easier to read and maintain. Variables work with strings, integers, booleans, objects, and arrays. Combining variables with built-in functions like uniqueString() and the ternary operator makes Bicep templates intelligent and environment-aware.
