ARM Day: Infrastructure as Code workout with Bicep

Warmup: What is Infrastructure as Code

The cloud opened the door to the ability for anyone, with the right permissions, to create and manage infrastructure resources. With this new power also came new challenges in managing infrastructure and new practices started to emerge.

Infrastructure as Code (IaC), as the name implies, is a code-based definition of infrastructure. This allows for automation of resource deployment resulting in fewer human errors and faster recovery times. Practices like version control and code reviews can also be implemented for visibility and change tracking.

We keep the infrastructure code in the same repository as the applications it hosts; if there is ever a need for it to move then we can update a few areas and redeploy the complete application with a relatively quick turnaround time.

Each cloud provider has their own implementation of Infrastructure as Code, and there are some cloud agnostic implementations as well.

Set 1: ARM, Bicep and a little Terraform

Azure Resource Manager (ARM) templates provide the ability to define Azure resources declaratively using JSON notation. The other choice was to manually create resources or use scripts with Azure CLI or PowerShell. While ARM templates simplified the creation and visibility of resources, the JSON formatting is quite verbose and has a high learning curve. Microsoft received multiple points of feedback around this and that is how Bicep came about.

Bicep is a domain-specific language built as an abstraction of ARM templates and has a syntax that is cleaner and easier to read. This abstraction gives multiple benefits – one being that there is no change to the command to deploy templates. There are also commands to compile Bicep templates to ARM as well as decompile ARM templates to Bicep (See the bonus section for some exciting tooling around this). So, if you have a collection of ARM templates that has been built over the years you don’t have to start over when making the switch.

Bicep and ARM template for a Storage Account
Bicep and ARM template for a Storage Account

While discussing IaC templates it is difficult to not bring up the comparison to Terraform. Terraform is a cloud agnostic tool for managing resources. One of the main differences is that since it is cloud agnostic it must manage the state of resources in a file, where in Azure, the Azure Resource Manager service manages state. Keep in mind that ‘cloud agnostic’ does not mean you can use the same template to multiple clouds – each has their own resource types and details. Though if this is your jam, the Microsoft documentation does include snippets of the Terraform code for each of its resources.

At MercuryWorks our focus is on Microsoft Azure, so we opted for Azure Resource Manager (ARM) templates and then migrated to Bicep when it was released.

Set 2: Basics of Bicep

Let’s look at some of the basics and a couple features of Bicep. In the above image there was an example of a Bicep template for deploying a Storage Account. This is a complete and valid Bicep file ready to be deployed (pending that ‘storage01’ is available).

  • resource – A keyword to indicate this block is a resource to be deployed
  • stg – Symbolic name that can be used to reference the resource other places in a bicep template
  • ‘Microsoft.Storage/storageAccounts@2019-06-01’ – Resource type and API version.
  • {} – Declaration of the resource and resource specific properties

Most of the time there will be more than one resource in a file, but the same concepts apply to each resource. In the following example there is a definition for an Azure SQL Server and Database.

A couple added points to notice in this Bicep file compared to the other one are –

  • parent – This property in the sqldatabase references the sqlserver symbolic name. During deployment it will be understood that the sqldatabase is associated with, and dependent on sqlserver.
  • param – These are parameters and can be referenced multiple times in the file. Parameters can have a default value but can also be overwritten with the use of a parameters file or buy a parameter option in the command line. Attributes can indicate secure parameters, set lengths, max and mins, etc.

Set 3: Digging deeper into Bicep

The basic Bicep files can get you far on the road to an Infrastructure as Code strategy, however there are more features that can take these templates to a more professional level.

In a full infrastructure setup, it is unlikely to deploy a single resource. For example, a web application could potentially have an App Service Plan, App Service, Azure SQL Server and Database, among other resources. It is possible to put all these resource definitions in the same file, however, for a level of abstraction that allows for resource definition reuse you can use modules.

Modules are bicep files with resource definitions that are deployed from a separate bicep file. So far, we have seen two bicep files, one for a Storage Account and one for an Azure SQL Server and Database. The Bicep file below references each of the earlier files using modules.

This Bicep file is what will be used in the deployment command and if the referenced files are in the correct location, all the resources will be deployed.

Another benefit of using modules is being able to define the scope for deployment. All these resources are being deployed from the same file and by default will be deployed to the same Resource Group. By adding a scope property to a module, the destination Resource Group can be changed.

There are many other benefits of Bicep modules that make them the preferred template set up.

Superset! Some Bicep Tools

As a bonus I wanted to bring up the Bicep extension for Visual Studio Code. This extension has syntax checking that is specific to the API version set for the resource as well as intellisense while writing files.

For example, when using modules if a required parameter is not included in the params object it will have the red warning squiggly (technical term, of course) and when hovered, tell you the property missing.

code snippet missing param property error on module
Missing param property error on module

Something I alluded to previously relating to Bicep being able to compile to ARM and vice versa, is the ability to paste JSON into a file with a bicep extension and have it automatically convert to Bicep. Of course, this paste decompilation along with the command to decompile is a best-effort action, so while it may not always be perfect it will get you close.

JSON paste decompilation to Bicep and warning
JSON paste decompilation to Bicep and warning


Using Bicep for our Infrastructure as Code templates has helped in our consistency and speed in deploying infrastructure for the applications we build. We have been able to create a set of standard template files that we use as a starting point for applications.

Contact us if you would like to see what all the hype about IaC is about. We can assist with getting new projects documented and scripted or creating templates for existing infrastructure you would like more visibility around.


Want brilliance sent straight to your inbox?