Bicep Expressions and Functions
Expressions and functions add intelligence to Bicep templates. Instead of hardcoding values, expressions calculate them dynamically. Bicep provides dozens of built-in functions that generate unique names, retrieve resource metadata, manipulate strings, perform math, and work with arrays and objects. Mastering these functions makes templates flexible and production-ready.
What Is an Expression in Bicep?
An expression is any value that Bicep evaluates at deployment time. Expressions go wherever a value is expected — inside parameters, variables, resource properties, and outputs.
// Simple literal (not an expression)
param location string = 'eastus'
// Expression using a function
var uniqueSuffix = uniqueString(resourceGroup().id)
// Expression using string interpolation
var storageName = 'st${uniqueSuffix}'
// Expression using a ternary operator
var sku = environment == 'prod' ? 'Standard_GRS' : 'Standard_LRS'
Categories of Bicep Functions
+----------------------------------------------------------+ | Bicep Function Categories | +------------------+---------------------------------------+ | Category | Purpose | +------------------+---------------------------------------+ | String | Manipulate and format text | | Numeric | Math operations | | Array | Work with lists | | Object | Work with key-value pairs | | Resource | Get resource metadata | | Deployment | Get deployment context | | Date/Time | Work with timestamps | | Logical | Conditional logic | +------------------+---------------------------------------+
String Functions
concat() – Joins strings together
var appName = 'webapp'
var env = 'prod'
// concat() joins multiple strings
var fullName = concat(appName, '-', env) // 'webapp-prod'
// String interpolation is cleaner (preferred)
var fullNameAlt = '${appName}-${env}' // 'webapp-prod'
toLower() and toUpper() – Change letter case
param environment string = 'PRODUCTION' // Normalize to lowercase for resource naming var envLower = toLower(environment) // 'production' var envUpper = toUpper(environment) // 'PRODUCTION'
replace() – Swap part of a string
var name = 'my-app-name' // Storage accounts cannot contain hyphens – replace them var storageName = replace(name, '-', '') // 'myappname'
substring() – Extract part of a string
var fullText = 'productionEnvironment' // Get characters starting at position 0, taking 4 characters var short = substring(fullText, 0, 4) // 'prod'
take() – Get first N characters
var longName = 'developmentenvironment' // Take first 8 characters var shortName = take(longName, 8) // 'developm'
contains() – Check if a string has a value
var resourceName = 'prod-webapp-eastus' // Returns true if the string contains 'prod' var isProd = contains(resourceName, 'prod') // true
trim() – Remove leading and trailing spaces
var rawInput = ' eastus ' var cleanInput = trim(rawInput) // 'eastus'
uniqueString() – Generating Unique Resource Names
This is one of the most used functions in Bicep. It generates a deterministic 13-character hash from input values. Deterministic means the same input always produces the same output — so re-deploying creates no duplicates.
// Always produces the same result for the same resource group
var suffix = uniqueString(resourceGroup().id)
// Combine with a prefix for a readable unique name
var storageAccountName = 'st${suffix}'
// Combine multiple seeds for more uniqueness
var uniqueName = uniqueString(resourceGroup().id, deployment().name)
How uniqueString Works
Input: resourceGroup().id
= '/subscriptions/aaaa/resourceGroups/myRG'
│
▼
[Hash Algorithm]
│
▼
Output: 'xkpq4r7nm2abc' (always the same for same input)
│
▼
Prefix + Output = 'stxkpq4r7nm2abc'
Resource Functions
resourceGroup() – Get the current resource group details
// Get the resource group ID
var rgId = resourceGroup().id
// Get the resource group name
var rgName = resourceGroup().name
// Get the resource group location
var rgLocation = resourceGroup().location
// Use the resource group location for all resources
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: 'mystorage001'
location: resourceGroup().location // inherit from resource group
sku: { name: 'Standard_LRS' }
kind: 'StorageV2'
}
subscription() – Get the current subscription details
var subId = subscription().subscriptionId var subName = subscription().displayName var tenantId = subscription().tenantId
deployment() – Get the current deployment details
var deploymentName = deployment().name var deploymentLocation = deployment().location
Numeric Functions
// min() – returns the smallest number var smallerValue = min(5, 10) // 5 var smallestInArray = min([3, 7, 1]) // 1 // max() – returns the largest number var largerValue = max(5, 10) // 10 // add, sub, mul, div, mod var sum = 5 + 3 // 8 var difference = 10 - 4 // 6 var product = 3 * 4 // 12 var quotient = 10 / 2 // 5 var remainder = 10 % 3 // 1
Array Functions
length() – Count items in an array
var regions = ['eastus', 'westus', 'centralus'] var regionCount = length(regions) // 3
union() – Merge two arrays or objects
var baseTags = {
environment: 'prod'
managedBy: 'Bicep'
}
var extraTags = {
project: 'ecommerce'
}
// Combine both tag objects
var allTags = union(baseTags, extraTags)
// Result: { environment: 'prod', managedBy: 'Bicep', project: 'ecommerce' }
contains() – Check if array has a value
var allowedRegions = ['eastus', 'westus'] var isAllowed = contains(allowedRegions, 'eastus') // true
first() and last() – Get first or last item
var names = ['alpha', 'beta', 'gamma'] var firstItem = first(names) // 'alpha' var lastItem = last(names) // 'gamma'
Logical Functions
if() – Return one value or another based on a condition
param environment string = 'prod' // if(condition, trueValue, falseValue) var instanceCount = if(environment == 'prod', 3, 1) // Ternary operator does the same (preferred syntax) var instanceCountAlt = environment == 'prod' ? 3 : 1
and(), or(), not()
param environment string = 'prod' param region string = 'eastus' var isHighAvailability = and(environment == 'prod', region == 'eastus') // true only when BOTH conditions are true var useRedundancy = or(environment == 'prod', environment == 'staging') // true when EITHER condition is true var isNotProd = not(environment == 'prod') // true when condition is false
The Ternary Operator – Conditional Expressions
The ternary operator is the most common expression in real Bicep templates. It chooses between two values based on a condition.
Syntax: condition ? valueWhenTrue : valueWhenFalse
+-------------------+
| condition? |
+-------------------+
│
┌───┴───┐
true false
│ │
▼ ▼
value1 value2
param environment string = 'prod' // Storage redundancy based on environment var storageSku = environment == 'prod' ? 'Standard_GRS' : 'Standard_LRS' // App Service tier based on environment var appTier = environment == 'prod' ? 'P1v3' : 'B1' // Enable backups only in production var backupEnabled = environment == 'prod' ? true : false // Set replica count var replicas = environment == 'prod' ? 3 : 1
Complete Example – Functions in a Real Template
param environment string = 'prod'
param appName string = 'orderservice'
param location string = resourceGroup().location
// Build consistent names using string functions
var cleanAppName = toLower(replace(appName, ' ', ''))
var uniqueSuffix = take(uniqueString(resourceGroup().id), 6)
var storageAccountName = 'st${cleanAppName}${uniqueSuffix}'
var webAppName = 'app-${cleanAppName}-${environment}'
// Conditional settings based on environment
var storageSku = environment == 'prod' ? 'Standard_GRS' : 'Standard_LRS'
var appServiceSku = environment == 'prod' ? 'P1v3' : 'B1'
var httpsOnly = environment == 'prod' ? true : false
// Tags using union to combine base and extra tags
var baseTags = {
managedBy: 'Bicep'
environment: environment
}
var appTags = union(baseTags, {
application: appName
costCenter: 'IT-${toUpper(environment)}'
})
// Resources
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageAccountName
location: location
tags: appTags
sku: {
name: storageSku
}
kind: 'StorageV2'
properties: {
supportsHttpsTrafficOnly: httpsOnly
}
}
resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
name: 'asp-${cleanAppName}-${environment}'
location: location
tags: appTags
sku: {
name: appServiceSku
}
}
// Outputs using functions
output storageAccountName string = storageAccount.name
output webAppUrl string = 'https://${webAppName}.azurewebsites.net'
output deployedRegion string = toUpper(location)
Quick Function Reference
| Function | Example | Result |
|---|---|---|
| uniqueString() | uniqueString(resourceGroup().id) | 'xkpq4r7nm2abc' |
| toLower() | toLower('PROD') | 'prod' |
| toUpper() | toUpper('prod') | 'PROD' |
| replace() | replace('my-app', '-', '') | 'myapp' |
| take() | take('production', 4) | 'prod' |
| length() | length(['a','b','c']) | 3 |
| contains() | contains('prod-app', 'prod') | true |
| concat() | concat('app', '-', 'prod') | 'app-prod' |
| union() | union({a:1}, {b:2}) | {a:1, b:2} |
| resourceGroup() | resourceGroup().location | 'eastus' |
| subscription() | subscription().subscriptionId | 'aaaa-bbbb-...' |
| min() | min(3, 7) | 3 |
| max() | max(3, 7) | 7 |
Summary
Bicep expressions and built-in functions turn static templates into dynamic, intelligent infrastructure code. String functions format and clean names. The uniqueString() function generates stable unique suffixes. Resource functions like resourceGroup() and subscription() retrieve deployment context. The ternary operator enables environment-aware configurations. Combining these tools results in templates that adapt automatically to different environments and requirements.
