The Intelligent Blueprint: Using Bicep Variables and Conditionals to Build Adaptable Infrastructure

Mid/Senior Engineer Asked at: Microsoft, any company on Azure

Q: Explain how you use variables and conditional logic in Bicep to manage differences between environments like dev and prod.

Why this matters: This question tests your ability to move from static scripts to dynamic, intelligent templates. The interviewer wants to know if you can build a single, authoritative blueprint that can adapt to different contexts, which is the hallmark of a scalable and maintainable IaC practice.

Interview frequency: High for any role that requires building and managing multiple environments.

❌ The Death Trap

The candidate gives a purely syntactic answer, describing what a variable is and what a ternary operator does, without connecting it to a real-world strategy.

"You use the `var` keyword to create a variable. For conditionals, you use the ternary operator, which is a question mark and a colon. So you can say `isProd ? 'Premium_LRS' : 'Standard_LRS'`. It's like an if-statement."

This is a low-level, mechanical explanation. It shows you know the language features but not the architectural patterns they enable.

🔄 The Reframe

What they're really asking: "How do you encode your team's operational logic and business rules directly into your infrastructure blueprints? Can you design a single source of truth that is smart enough to configure itself differently based on its target environment?"

This reframes the question from a discussion of syntax to a strategic one about creating self-adapting, intelligent systems. It's about building a template that doesn't just describe resources, but also describes the *logic* of your environments.

🧠 The Mental Model

The "Smart Lego Instruction Manual" model. Your Bicep template isn't just a static set of instructions; it's a dynamic guide that changes based on who is building the Lego set.

1. Parameters are the Questions: The manual starts by asking the builder questions. `param environment string` is the question, "Are you building the 'Castle for Kids' (`dev`) or the 'Fortress for Experts' (`prod`)?" The `@allowed` decorator ensures they can only give a valid answer.
2. Variables are the Calculated Decisions: Based on the answers to the questions, the manual makes internal calculations. `var storageSku = ...` is the manual saying, "Okay, since you're building the 'Fortress for Experts', I have calculated that you will need the 'unbreakable platinum bricks' (`Premium_LRS`)." Variables are used to centralize and name this complex logic.
3. The Ternary Operator is the Fork in the Road: This is the specific instruction in the manual that says, "If building the Fortress, use the platinum bricks. Otherwise, use the standard red bricks." It's the mechanism for implementing the decision calculated by the variable.

✅ The Answer

My Thinking Process:

"My core principle is to make my templates as intelligent as possible to reduce the chance of human error. The goal is to have a single, canonical blueprint for a service. Variables and conditionals are the tools that allow this single blueprint to intelligently adapt itself for different environments like `dev` and `prod`."

Building the Intelligent Template: A Practical Example

Let's take a common scenario: we need a storage account that uses the cheap `Standard_LRS` SKU for development, but the high-performance `Premium_LRS` SKU for production. A naive approach would be to have two separate Bicep files, which leads to configuration drift. The intelligent approach is to encode this logic into a single file.

Step 1: Ask the Right Question (The Parameter)
First, I define a parameter to ask the user for the target environment. Crucially, I use the `@allowed` decorator to make it impossible for them to provide an invalid answer. This is a key safety feature.

@description('The target environment for the deployment.') @allowed([ 'prod' 'non-prod' ]) param environment string

Step 2: Make the Decision (The Variable and Conditional)
Next, I create a variable to hold the outcome of our business logic. This is where I use the ternary operator. This centralizes the logic in one place, making it easy to read and maintain.

// Decide which SKU to use based on the environment parameter var storageSkuName = (environment == 'prod') ? 'Premium_LRS' : 'Standard_LRS'

Step 3: Apply the Decision (The Resource)
Finally, in the resource block, I don't use any complex logic. I simply refer to the variable. This keeps my resource definitions clean and focused on describing the 'what', while the 'why' is handled in the variable section.

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: '...' location: '...' sku: { name: storageSkuName // Use the calculated variable here } kind: 'StorageV2' }

Verifying Before Committing: The `-WhatIf` Safety Net

Before ever deploying, I would validate this logic using the `-Confirm` or `-WhatIf` switch in PowerShell. This allows me to see a preview of what Azure *will* create. I can run it once with `non-prod` and see that it correctly chooses `Standard_LRS`, and then run it again with `prod` to confirm it chooses `Premium_LRS`. This turns a potentially risky deployment into a predictable and verifiable operation."

🎯 The Memorable Hook

This breaks down the components into a clear, first-principles model of a cognitive process—question, decision, logic—demonstrating a deep and memorable understanding.

💭 Inevitable Follow-ups

Q: "When would you choose to use a variable versus putting the conditional logic directly in the resource block?"

Be ready: "I always default to using a variable. It follows the 'Don't Repeat Yourself' (DRY) principle. If you need that same logic in multiple places, a variable defines it once. More importantly, it separates the 'decision logic' from the 'resource definition,' making the template far more readable and self-documenting. Putting complex ternaries inside a resource block is like writing a magic number in code; it obscures the intent."

Q: "What if the logic becomes more complex than a simple if/else? For example, you have dev, staging, and prod environments, all with different SKUs."

Be ready: "That's a great scenario. You could chain ternary operators, but that gets messy. A much more elegant solution is to use a variable to define a map or an object. The variable would look like `var skuMap = { prod: 'Premium_LRS', staging: 'Standard_GRS', dev: 'Standard_LRS' }`. Then, in the resource, the SKU name would simply be `skuMap[environment]`. This pattern is incredibly powerful for managing complex, multi-environment configurations in a clean and scalable way."

Written by Benito J D