Wanna keep your infrastructure as code tidy and future-friendly? Say hello to Bicep modules — the human friendly version of ARM templates 😄


🎯 What This Post is About

In this hands-on exercise, I took my existing Bicep template and broke it up using modules — little reusable building blocks that keep your main file clean and organized.

Here’s what I learned:

  • 📦 How to extract App Service-related stuff into its own reusable module
  • 🎯 How to pass parameters into that module (like location, name, and environment)
  • 🧾 How to return values (outputs) from the module back to the main deployment
  • ✅ How to test and verify it all using the Azure CLI and the Azure Portal

🛠️ What’s a Bicep Module?

Think of your main Bicep file like the director of a movie — it calls the shots. A module is like a supporting actor: focused, self-contained, and easy to reuse in other projects. Instead of putting everything in one script, you give roles to individual modules and tell them when to perform.


📁 Step 1: Creating the Module File

First, I created a folder called modules and a file inside it called appService.bicep. Then I moved all the App Service logic there.

Here's what it looks like:

param location string
param appServiceAppName string

@allowed([
  'nonprod'
  'prod'
])
param environmentType string

var appServicePlanName = 'toy-product-launch-plan'
var appServicePlanSkuName = (environmentType == 'prod') ? 'P2v3' : 'F1'

resource appServicePlan 'Microsoft.Web/serverfarms@2024-04-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: appServicePlanSkuName
  }
}

resource appServiceApp 'Microsoft.Web/sites@2024-04-01' = {
  name: appServiceAppName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
  }
}

output appServiceAppHostName string = appServiceApp.properties.defaultHostName

✨ Why this is cool:

  • The module is self-contained. It knows everything it needs to deploy App Services.
  • We can reuse this module in other projects without touching the rest of our infrastructure.

🧹 Step 2: Cleaning Up the Main File

I went into my main.bicep and:

  • Removed the App Service resources and variables
  • Kept the parameters (since the module still needs them)

Then I added this near the bottom:

module appService 'modules/appService.bicep' = {
  name: 'appService'
  params: {
    location: location
    appServiceAppName: appServiceAppName
    environmentType: environmentType
  }
}

output appServiceAppHostName string = appService.outputs.appServiceAppHostName

So now the main file stays focused, and all the heavy lifting is handled inside the module.


🧪 Step 3: Time to Deploy!

I logged into Azure CLI:

az login

Then I created a resource group:

az group create --name BicepRG --location westus

And finally deployed everything:

az deployment group create \
  --resource-group BicepRG \
  --name main \
  --template-file main.bicep \
  --parameters environmentType=nonprod

🧾 Step 4: What Happened in the Portal?

In Azure Portal:

  1. I went to Resource Groups > BicepRG
  2. Clicked the Deployments tab
  3. Saw two entries: main and appService (yes, the module shows up!)
  4. Opened main > Outputs — there it was: appServiceAppHostName
  5. Copied the hostname, pasted it in a browser, and 💥 saw the default App Service welcome page!

🧠 In Short: Why Bicep Modules Are Worth It

Concept What I Gained
Modules Cleaner, reusable code
Parameters Flexible inputs passed from parent template
Outputs Values exposed from module to parent
Separation of Concerns Clear boundaries between responsibilities
Reusability Use the same logic in multiple environments/projects

🔚 Final Thoughts

Bicep modules reminded me of organizing your closet: instead of stuffing all your clothes into one drawer, you put shirts in one section, pants in another, socks somewhere else — then label it all! 🧦👕

This exercise helped me appreciate structure and scalability when it comes to managing cloud infrastructure.


🚀 Wanna follow my Azure learning journey?

Stick around — I’m sharing it all, wins and stumbles included 😄

You can find me on LinkedIn — drop me a message and just say hi 👋

Would love to hear what you're working on or learning!