The upcoming Module feature for Azure Bicep really enhances the new ARM Template alternative language in a way that ARM JSON never did. Using Azure Bicep Modules you can easily create reusable bicep code that will eliminate copy/paste of bicep code across multiple deployment projects. Azure Bicep Modules do not require any special syntax, and you can create modules that are either a single .bicep file or even a directory full of multiple .bicep files.

Let’s dig into how to enable Azure Bicep code reuse with Modules!

Related: If you’re new to Azure Bicep, then we recommend you go read the “Get Started with Azure Bicep – Alternative to ARM Templates” article written by Chris Pietschmann.

What is an Azure Bicep Module?

In the simplest terms, an Azure Bicep Module is a set of bicep code that is enabled for reuse throughout multiple places within your Infrastructure as Code (IaC) deployment. This feature helps reduce the amount of copy/pasted code within a single Azure Bicep deployment project, or even across multiple projects by sharing bicep module code.

Modules is an important feature of Azure Bicep that is instrumental in writing more reusable and maintainable code. Once you begin to implement modules throughout your code, you’ll never want to stop using them! You can write modules to reuse within a single Azure Bicep deployment, or even create a library of modules to reuse across multiple deployments.

Declare an Azure Bicep Module

At the core, an Azure Bicep Module is written using bicep code that is the same as any other bicep code. There’s no special syntax for writing modules. A module could be a single .bicep file or even a directory containing multiple .bicep files.

Generally, modules will be written with one or more parameters (using the param keyword) and outputs (using the output keyword). The parameters enable variables to be passed into the module so it can be configured by the calling bicep code. The outputs enable values from the module to be passed out from it and then referenced by the calling bicep code just like how resource declarations have outputs that can be referenced by other code.

Single File Module

A single file Azure Bicep module is declared by writing bicep code within a single .bicep file. This can be any standard bicep code, as modules do not require any special syntax to write.

Below is an example of a single file bicep module (possibly named multipleStorageAccounts.bicep) that can be used to create multiple Azure Storage Accounts by passing in an array of account names.

// ****************************************
// Azure Bicep Module:
// Create multiple Azure Storage Accounts
// ****************************************

// Parameter of Azure Region to use
param location string

// Parameter of Storage Account Names
param accountNames array 

// Create multiple Storage Accounts with names passed in 'accountNames' parameter
resource[] storageAccounts 'Microsoft.Storage/storageAccounts@2019-06-01' = {
  for name in accountNames: {
    name: name          // Storage account name
    location: location  // Azure Region
    kind: 'Storage'
    sku: {
      name: 'Standard_LRS'

// Output Storage Accounts Ids in Array
output storageAccountIds array = [
  for account in storageAccounts: { account.id }

This example single file module accepts a couple parameters for an Array of accountNames for the Storage Accounts and the location defining the Azure Region to create the Storage Accounts in. There is also a storageAccountIds Output that will output an Array of the Ids for the Storage Accounts created.

Directory-based Module with Multiple Files

Another way to declare an Azure Bicep Module is to create the module with multiple .bicep files within the same directory. There is still no special syntax to writing modules using multiple files within a directory. You write the module with regular Azure Bicep code separated out into multiple .bicep files within the root of the directory. When Azure Bicep compiles the code, it will combine all the files within the directory.

Here’s are example file names for breaking out Azure Bicep code into multiple .bicep files when writing a directory-based module:

  • parameters.bicep – This file contains the param declarations for all the input parameters for the module.
  • outputs.bicep – This file contains the output declarations for all the output variables for the module.
  • main.bicep – This file may contain all or some of the bicep code for the module.
  • *.bicep – Any additional .bicep files could be used to contain code broken out into multiple files for organization.

Using Modules in Azure Bicep Deployments

When writing Azure Bicep code for a deployment, the module keyword is used to declare the usage of an Azure Bicep Module. The usage is similar to the resource keyword where the module keyword is followed by the symbolic name followed by the relative path of the module to use. Also, the input parameters to pass into the module are also defined within the module block.

Here’s the basic syntax for declaring the usage of an Azure Bicep Module:

module <symbolic-name> '<module-path>' {
  // Input Parameters
  <parameter-name>: <parameter-value>

The different elements (as seen by the placeholders in the above example) of the module declaration in Azure Bicep code are as follows:

  • module keyword – Use for declaring the block of code that defines the Azure Bicep Module to use.
  • Symbolic name – This is an identifier (or name) within the Azure Bicep project that can be used to reference this module in other locations within the bicep code. Keep in mind, this is not the name of any Azure resources deployed, this name is only for referencing this module within the Azure Bicep code.
  • Module path – Specifies the location of the Azure Bicep Module code. This is specified using relative path (such as ../modules/multipleStorageAccounts directory or ../modules/multipleStorageAccounts.bicep single file). The path declaration supports both / and \ characters.
  • Parameter name and value – Each input parameter for the Azure Bicep Module will be defined with the parameter name and value separated by a colon (:) character. As many parameters required for the module can be defined. Any parameters with default values in the module can be left out.

Use Single File Module

Declaring the usage of a single file Azure Bicep Module specifies the individual .bicep file for the module using a relative path.

Here’s an example of declaring the usage of a single file module:

module storageAccounts '../modules/multipleStorageAccounts.bicep` {
  location: 'northcentralus'
  accountNames: [

Use Directory-based Module

Declaring the usage of a directory-based Azure Bicep Module specifies the directory for the module. This directory will contain one or more .bicep files that make up the module.

Here’s an example of declaring the usage of a directory-based module:

module storageAccounts '../modules/multipleStorageAccounts` {
  location: 'northcentralus'
  accountNames: [

Wrap Up

The upcoming Modules feature for Azure Bicep will help write reusable bicep code that will eliminate copy/paste of bicep code. You will be able to reuse Azure Bicep code within the same project or even multiple projects. This is an extremely powerful feature that really enhances the productivity gains of using Azure Bicep instead of ARM Templates written in JSON.

Happy automating Azure resource deployment / management using Azure Bicep!

P.S. If you’re reading this article on a website that is not Build5Nines.com, then this site copied and republished this article illegally and is violating copyright law. Please visit Build5Nines.com and subscribe to our newsletter to stay up-to-date on the latest updates in cloud and enterprise technology! Sorry for this message, as we’ve been having issues with other sites stealing our content and republishing it as their own!

Microsoft MVP

Chris Pietschmann is a Microsoft MVP, HashiCorp Ambassador, and Microsoft Certified Trainer (MCT) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to large enterprises. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.
HashiCorp Ambassador Microsoft Certified Trainer (MCT) Microsoft Certified: Azure Solutions Architect