How to use the `this` namepsace in Bicep to check resources
Learn how to prevent common deployment failures from immutable property changes
Often you face challenges when deploying Azure resources against existing one: templates behave differently for new resources versus existing ones.
Some properties can only be set during creation, whilst others should be preserved during updates. You can't always know which scenario will happen until runtime. The this namespace solves this problem by enabling runtime checks and conditional logic based on the resource's existence.
In this guide, you will:
- Use
this.exists()to determine if a resource already exists at deployment time. - Access existing resource properties with
this.existingResource(). - Set different values for new resources versus updates.
- Enable the experimental
thisnamespace feature in your Bicep environment.
Prerequisites
Before you dive in, you need to have:
- Bicep CLI nightly build installed.
- A
bicepconfig.jsonfile in your project.
To install the nightly CLI build, you can use:
iex "& { $(irm https://aka.ms/bicep/nightly-cli.ps1) }"You can enable the experimental feature by creating or updating your bicepconfig.json file in your project root:
{
"experimentalFeaturesEnabled": {
"thisNamespace": true
}
}Check resource existence
The this.exists() function is newly introduced in Bicep and returns a boolean value. This boolean value indicates whether the resource already exists in Azure at deployment time.
You can use this.exists() to set different default values for new versus existing resources:
resource storage 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: storageAccountName
location: location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
// New storage accounts default to disabled public access
// Existing accounts keep their current configuration
allowBlobPublicAccess: this.exists() ? false : true
}
}The function only works at deployment time, not compilation time. Azure examines the current state of your subscription and then returns the result. The Bicep compiler translates this.exists() to [not(empty(target('full')))] in the generated ARM template.
Access existing resource properties
The other function newly introduced is the this.existingResource() function. This returns the complete resource object if it exists, or returns null if it doesn't. With this function, you can read the current property values and preserve them during updates.
By combining this.existingResource() with the safe navigation operator (?.), you can access nested properties without causing errors:
resource storage 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: storageAccountName
location: location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
// Preserve the existing retention policy if it exists
deleteRetentionPolicy: this.existingResource().?properties.deleteRetentionPolicy
}
}Using the ?. operator prevents Azure from throwing errors when the resource doesn't exist. If this.existingResource() returns null, the whole expression evaluates to null.
Combine existence checks with property access
It's also possible to use both in combination for more complex scenarios. The following pattern is useful when you want to apply different configurations based on the current resource state.
In the following template, both this.exists() and this.existingResource() are used:
resource storage 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: 'mystorageaccount'
location: 'westus'
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
// New accounts get secure defaults
// Existing accounts preserve their current settings
allowBlobPublicAccess: this.exists()
? this.existingResource().?properties.allowBlobPublicAccess
: false
}
resource fileService 'fileServices' = {
name: 'default'
properties: {
// Always preserve existing retention policies
shareDeleteRetentionPolicy: this.existingResource().?properties.shareDeleteRetentionPolicy
}
resource fileShare 'shares' = {
name: 'exampleshare'
properties: {
// Keep the current access tier if it exists
accessTier: this.existingResource().?properties.accessTier
}
}
}
}Using the above pattern works with nested resources. Each resource independently checks the existence and accesses the current state. The template adapts to the presence or absence of the parent storage account and its nested resources.
Understand function limitations
The this namespace functions have specific limitations (or constraints) that you should understand before implementing.
These functions only work inside resource property blocks. You cannot use them in:
- Resource names
- Module parameters
- Top-level loop expressions
This restriction exists because the functions depend on the resource context.
// ✓ Valid - inside properties block
resource storage 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: storageAccountName
properties: {
allowBlobPublicAccess: this.exists() ? false : true
}
}
// ✗ Invalid - in resource name
resource storage 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: this.exists() ? 'existing' : 'new' // Error
properties: {}
}Summary
This quick guide demonstrated how to use the this namespace in Bicep templates. You've covered:
- Enable the experimental feature
thisNamespacein thebicepconfig.jsonfile. - Used
this.exists()to determine if resources already exist at deployment time. - Accessed existing configurations with
this.existingResource()and safe navigation operators - Implemented different behaviors for new versus existing resources
By leveraging the this namespace, you eliminate the need for separate create and update templates while preventing deployment failures from immutable property changes. To learn more, check out the official documentation in the Bicep repository.