Introduction
If you’ve worked with Azure Resource Manager (ARM) templates before, you probably know how powerful they are—but also how cumbersome they can become. The JSON syntax is verbose, the structure can be rigid, and making even simple changes often requires navigating deeply nested declarations.
That’s why Microsoft introduced Azure Bicep—a domain-specific language built to make infrastructure as code on Azure more approachable. It keeps all the capabilities of ARM templates but removes much of the complexity. With Bicep, you’re still working within the ARM deployment model—but using a language that’s easier to write, read, and maintain.
In this guide, we’ll take a practical, step-by-step approach to understanding Bicep. You’ll learn:
- What Azure Bicep is and how it works
- How it compares to traditional ARM templates
- Why many teams are choosing Bicep for modern Azure infrastructure
- How to write and deploy your first Bicep file using the Azure CLI
You don’t need to be an expert in ARM templates to follow along. If you’re comfortable with the basics of Azure and want a cleaner, more streamlined way to define your infrastructure, this guide will help you get there—one concept at a time.
Why Should You Care About Azure Bicep?
Before we dive deeper into what Bicep can do, it’s important to clarify how it fits into the bigger picture.
Azure Resource Manager (ARM) is the engine that manages and deploys resources in Azure.
ARM templates are a JSON-based format used to describe your infrastructure to that engine.
Bicep is a modern, more readable language that compiles down into ARM templates. You’re still using the ARM system—but with a language that’s far easier to work with.
Understanding this distinction helps avoid a common misconception: Bicep isn’t a replacement for ARM—it’s a better way to write for it.
With that context in mind, let’s look at why Bicep is gaining momentum among developers and cloud engineers.
1. Azure-Native and Always Up to Date
Bicep is designed specifically for Azure and is tightly integrated with the platform. That means:
- You can use new Azure features and resource types as soon as they’re released
- You’re always aligned with the underlying ARM system—there’s no translation layer or external toolchain
- You benefit from native support without sacrificing reliability or consistency
This tight integration makes Bicep a dependable choice for real-world infrastructure work—not just a simplified syntax layer.
2. Clean, Readable Syntax
One of the biggest challenges with ARM templates is the JSON format. Even simple tasks often require dozens of lines of boilerplate code.
Bicep significantly reduces that overhead:
- No more curly braces, quotes around every key, or deeply nested structures
- Fewer lines of code for the same result
- Easier to scan, maintain, and review—especially in team settings
This isn’t just about saving keystrokes—it’s about making your infrastructure code easier to reason about.
3. A Developer-Friendly Experience
Bicep is designed with modern development in mind. You get:
- IntelliSense, syntax highlighting, and autocompletion in VS Code
- Built-in validation to catch mistakes before deployment
- Seamless integration with the Azure CLI and DevOps pipelines
These features combine to make Bicep feel less like a markup language and more like actual infrastructure programming—without the steep learning curve.
A Quick Recap Before We Move On
At this point, you’ve seen why Bicep is getting attention:
- It simplifies how we write infrastructure code
- It stays tightly aligned with Azure’s native deployment system
- It gives you modern tooling that makes day-to-day work more productive
Now let’s see it in action. In the next section, we’ll walk through a real-world example and compare Bicep to a traditional ARM template side by side.
How Does Bicep Compare to ARM Templates?
Now that you understand why Bicep is gaining traction, let’s take a closer look at how it actually works—starting with a direct comparison to traditional ARM templates.
Both Bicep and ARM templates define Azure resources in a declarative way, meaning you describe what you want to deploy, and Azure takes care of the rest. But where they differ is in how clearly and concisely that definition is expressed.
Let’s walk through a simple example: creating a resource group.
Creating a Resource Group in Bicep
Here’s what that looks like in Bicep:
|
|
This is short, focused, and easy to understand—even if you’ve never seen Bicep before. Each line serves a clear purpose, and the structure is intuitive. You’re describing exactly what you want to create, and the syntax stays out of your way.
The Same Resource Group in an ARM Template
Now here’s the equivalent ARM template in JSON:
|
|
This version does exactly the same thing—but the structure is heavier. You’re dealing with nested brackets, strict quoting, schema declarations, and more noise around the actual intent. For small tasks like this, it’s manageable—but as your infrastructure grows, so does the complexity.
Why Bicep Feels More Natural
Let’s break down the core differences:
Concept | ARM Template (JSON) | Bicep |
---|---|---|
Verbosity | High – includes schema, metadata, nesting | Low – just the essentials |
Readability | Nested, noisy syntax | Clean, declarative, human-friendly |
Learning Curve | Steep, especially for newcomers | Gentler and more approachable |
Maintenance | Changes can be tedious and error-prone | Easier to modify and refactor |
In short, Bicep helps you focus on what you want to build, instead of getting bogged down in how to describe it.
A Note on What’s Really Happening Behind the Scenes
Even though you’re writing in Bicep, Azure doesn’t treat it as a separate deployment model. When you deploy a .bicep
file, it gets automatically transpiled into an ARM template, which is what Azure uses under the hood.
So you’re still benefiting from the full power, security, and consistency of the ARM engine—you’re just using a much cleaner and more developer-friendly way to interact with it.
What’s Next?
Now that you’ve seen how Bicep simplifies Azure resource definitions, let’s put it into practice. In the next section, we’ll walk through setting up your environment and writing your first real Bicep script from scratch.
Writing Your First Bicep Script
Now that you’ve seen how Bicep compares to ARM templates, it’s time to get hands-on. In this section, we’ll walk through how to write your first Bicep script—from setting up your tools to writing and understanding the code line by line.
If this is your first time using infrastructure as code, don’t worry—we’ll take it step by step.
Step 1: Set Up Your Environment
Before we write any code, let’s make sure you have everything you need installed.
Tools You’ll Need:
- Azure CLI – used to deploy resources from the command line
- Bicep CLI – handles
.bicep
files and converts them to ARM templates under the hood - Visual Studio Code (VS Code) – recommended editor with Bicep extension for syntax support
If you’re new to Azure CLI or haven’t used it in a while, here’s a quick video to walk you through the basics:
Installation Instructions
-
Install the Azure CLI
👉 Follow the official guide here: Install the Azure CLI -
Install the Bicep CLI
Once the Azure CLI is installed, run the following command:1
az bicep install
-
Install the Bicep Extension for VS Code
Open Visual Studio Code, go to Extensions, and search for “Bicep”. Install the top result.
This setup only takes a few minutes, and once it’s done, you’re ready to start writing Bicep code with full tooling support.
Step 2: Create a New File
Let’s start by creating a new file in your project folder and naming it:
|
|
This will be your first infrastructure definition written in Bicep.
Step 3: Write Your Bicep Code
Paste the following into your main.bicep
file:
|
|
This script defines a resource group—one of the most basic building blocks in Azure. It’s a simple file, but it’s doing meaningful work. Let’s take a closer look at what’s going on.
Step 4: Understand the Code
Here’s a line-by-line breakdown of what this script does:
targetScope = 'subscription'
This line tells Azure where the deployment will occur. In this case, we’re targeting the subscription level, which is where resource groups live.
resource iaMachsResourceGroup ...
This declares a new resource and includes:
- A local name within the file (
iaMachsResourceGroup
) - The type of resource being created (
resourceGroups
) - The specific API version to use
name: 'iaMachsRG'
This is the name of the resource group that will appear in the Azure portal after deployment.
location: 'australiaeast'
This sets the Azure region where the resource group will be created.
A Quick Note on API Versions
You might be wondering about the part that looks like this:
|
|
That’s a combination of the resource type and the API version. Azure evolves quickly, and by specifying the version, you make sure your deployments behave consistently—even if Azure changes in the future. You can always check the latest API versions in the Azure REST API reference.
⚠️ What About the Squiggly Line?
If you see a squiggly line under 'australiaeast'
in VS Code, don’t worry—that’s the Bicep extension reminding you that hardcoded values are fine for learning, but not ideal for production code.
Later on, we’ll explore how to use parameters to make scripts like this reusable across environments. For now, feel free to leave it hardcoded—we’re here to learn the basics.
What’s Next?
Your script is complete and ready to be deployed. In the next section, we’ll use the Azure CLI to run this Bicep file and see the results directly in the Azure portal.
Deploying Your Bicep Script with Azure CLI
With your Bicep script ready, it’s time to deploy it to Azure and see it come to life. In this section, we’ll walk through how to deploy using the Azure CLI—step by step.
If this is your first time deploying infrastructure from the command line, take it one step at a time. You’re not just running a script—you’re learning how modern cloud infrastructure is built and managed.
Step 1: Sign in to Azure
Open your terminal and sign in to your Azure account:
|
|
This command opens a browser window where you can enter your Azure credentials. Once authenticated, the terminal will return a list of your subscriptions.
If you have access to more than one Azure subscription, be sure to set the one you want to use:
|
|
This ensures your deployment lands in the right place.
Step 2: Navigate to Your Project Folder
Make sure your terminal is pointed at the folder where you saved main.bicep
. For example:
|
|
Step 3: Run the Deployment Command
Now run the following command to deploy your Bicep file:
|
|
Let’s quickly break down what this command does:
Part of the Command | What It Means |
---|---|
az deployment sub create |
Tells Azure to create a subscription-level deployment |
--location australiaeast |
Specifies the region to store the deployment metadata (not the location of the resource itself) |
--template-file main.bicep |
Points to the Bicep file containing your infrastructure definition |
🧠 You might be wondering: “Why are we specifying
australiaeast
again, even though we already did that in the script?”That’s a great question. In your Bicep file, the
location
property inside the resource definition tells Azure where to deploy the resource itself. But in this CLI command, the--location
flag serves a different purpose: it tells Azure where to store the deployment metadata.So in this case, you’re saying:
“Please create a resource group in Australia East, and also store the deployment record itself in Australia East.”
This subtle distinction can be confusing at first, but it’s good to be aware of—especially when working with deployments at different scopes (subscription, management group, tenant).
Step 4: Confirm the Deployment
If the deployment succeeds, you’ll see a response that includes the provisioningState
:
|
|
You can also verify everything visually in the Azure portal:
- Visit portal.azure.com
- Go to Resource Groups
- Look for
iaMachsRG
in the list
If you see it there—congratulations, your first Bicep deployment is complete!
You’ve Just Taken a Big Step
That might’ve seemed like a small script and a simple command, but what you’ve just done is significant:
- You created an Azure infrastructure definition using code
- You deployed it using a reproducible, automated process
- You took your first step toward managing infrastructure like a cloud engineer
These are the same tools and workflows used in production environments across real-world teams.
What’s Next?
If you remember that squiggly line in the Bicep code earlier, it was warning us about hardcoded values like the region. That’s something we can improve with parameters, which allow us to make our templates flexible and reusable across different environments.
In the next article, we’ll take a closer look at Bicep parameters—and show you how to turn this static script into something far more adaptable.