Interview Preparation
Practice deep Bicep interview answers: syntax, architecture, deployment failures, and Bicep vs Terraform tradeoffs.
How Interviewers Test Bicep Knowledge
Interviewers at platform and DevOps roles test Bicep on three dimensions:
- Conceptual — Can you explain why Bicep exists and how it differs from ARM JSON and Terraform?
- Practical — Can you write and debug a Bicep template? Have you deployed real Azure resources with it?
- Judgment — Can you choose the right tool for the right context? Can you explain failure triage and recovery?
Never say "Bicep is better than Terraform" or vice versa. Always frame it as: "The right choice depends on cloud scope, team expertise, state complexity, and governance model." This signals platform engineering maturity.
Topic Coverage Cheatsheet
| Topic | Key concepts to know | Lesson reference |
|---|---|---|
| Bicep vs ARM JSON | Bicep compiles to ARM; shorter syntax, type system, no schema noise | Lessons 1-2 |
| Parameters and outputs | @allowed, @secure, @minLength, output chaining for modules | Lesson 3 |
| Dependency resolution | Symbolic references create implicit deps; dependsOn for side-effects | Lesson 4 |
| Modules | Reusable Bicep files; output-to-param wiring; Azure Verified Modules | Lesson 5 |
| Loops and conditions | for expression, if condition, existing keyword | Lesson 6 |
| Deployment scopes | RG, subscription, management group, tenant scope deployments | Lesson 7 |
| AKS with Bicep | VNet sizing, managed identity, networkProfile, OIDC issuer, role assignments | Lesson 9 |
| Bicep vs Terraform | State model, API currency, multi-cloud, governance, team cost | Lesson 10 |
| Debugging | 5-runbook model, operations list, what-if, policy denial triage | Lesson 15 |
Beginner Questions
Bicep is a domain-specific language that compiles to ARM JSON templates. It provides a cleaner, shorter syntax with a type system and compile-time validation while targeting the same Azure Resource Manager API as ARM JSON. It is not a wrapper — it produces identical ARM JSON output.
Shorter syntax, explicit type checking, compile-time errors instead of runtime failures, module support without copy-paste, and no JSON schema noise. ARM JSON requires hundreds of lines for what Bicep expresses in dozens.
A parameter is an external input set by the caller at deployment time. A variable is a computed value derived inside the template and not settable by the caller. Parameters make templates reusable; variables keep derived expressions DRY and avoid duplication.
A module is a separate Bicep file that encapsulates a set of related resources. A root template wires modules together by passing parameter values and consuming outputs. Modules enable ownership boundaries and reuse without duplication, similar to functions in programming.
Bicep builds a dependency graph automatically from symbolic references. If resource B references resource A using A.id or A.properties.x, Bicep infers that A must be created before B. Explicit dependsOn is only needed for side-effects not reflected in a property reference.
What-if runs a dry-run of the deployment and shows exactly what changes ARM would make: creates, modifications, deletions, and no-change resources. It is a mandatory safety check before production deploys because it catches unexpected deletes, policy violations, and unintended replacements.
Intermediate Questions
Declare outputs in the provider module (e.g. output subnetId string = vnet.properties.subnets[0].id). In the root template, reference it as networkModule.outputs.subnetId and pass it as a parameter to the consumer module. This creates a clean data contract between modules without hardcoding resource names.
The existing keyword tells Bicep to read an already-deployed resource from Azure without creating or managing it. This lets you reference properties like resource IDs from pre-existing infrastructure (provisioned outside the current template) without taking ownership of that resource in the deployment.
Use for loops to create multiple similar resources from an array, such as deploying N subnets or N storage accounts. Syntax: resource items 'type@version' = [for item in itemArray: { name: item.name ... }]. The output is an array of resources you can reference by index.
Incremental (default) creates or updates resources in the template and leaves any existing resources not in the template untouched. Complete mode deletes any resource in the target scope that is not present in the template. Incremental is safe for most deployments; complete mode is only appropriate when you want the RG to exactly mirror the template and you have reviewed what-if output for unexpected deletions.
Set the targetScope declaration at the top of the file. Options are resourceGroup (default), subscription, managementGroup, and tenant. Subscription-scoped templates can create resource groups and assign policies. Management group scope targets multiple subscriptions. This enables platform teams to provision entire landing zones from a single Bicep hierarchy.
Use @secure() on string parameters for passwords or keys — ARM never logs them. Reference secrets from Key Vault directly using the getSecret() function or by passing a Key Vault secret reference in the parameters file. Never hardcode secrets in the template or parameters file committed to source control.
Bicep vs Terraform: Interview Depth
See Lesson 10: Bicep vs Terraform Decision Guide for the full comparison. Common interview points distilled here:
The state model. Bicep relies on ARM to track deployment state — no external file to manage. Terraform uses an external state file that the team must provision, secure, lock, and back up. Both achieve idempotency but through fundamentally different mechanisms with different operational overhead.
When the organisation operates or plans to operate infrastructure on multiple cloud providers, when the team already has Terraform expertise and tooling at scale, or when unifying non-Azure resources (like DNS or GitHub teams) with Azure infrastructure under one IaC workflow is a priority.
When the platform is Azure-only, when the team does not want the operational burden of managing remote state, when immediate access to new Azure API features matters, or when deep Azure Policy integration is required. Bicep also has no binary to install in CI/CD — Azure DevOps and GitHub Actions have native tasks.
When Azure releases a new AKS feature, networking capability, or resource type, teams using Bicep can use it immediately because Bicep compiles to the ARM API directly. Teams using Terraform must wait for the AzureRM provider to implement support, which can take weeks to months for non-critical features.
Scenario-Based Questions
List the deployment operations to identify exactly which resources succeeded and which failed. Fix the root cause of the failure. Re-run the deployment in incremental mode — ARM will skip already-created resources and only create or update the missing ones. Never delete and rebuild when a partial deployment exists; understand the state first.
First check whether the cluster's managed identity has the Network Contributor role on the subnet or resource group. This is the most common cause. Also verify the identity type is UserAssigned and the identity resource was deployed before the cluster. Get the failing event with az deployment operation group list and look at the status message.
What-if catches unexpected property changes, unintended deletions (especially in complete mode), and policy violations before any resource is affected. Running it in dev also validates that the what-if gate in prod will work correctly. The command is fast and the cost of skipping it is a production incident waiting to happen.
Start with Azure Verified Modules as the baseline. Create a private Bicep Registry (backed by an Azure Container Registry) for organisation-specific modules with standard naming, tagging, and security configurations pre-applied. Teams consume versioned modules from the registry rather than copy-pasting templates. A platform team owns the registry and reviews module changes through pull requests.
In a well-functioning pipeline: (1) az bicep build on every pull request commit to catch compile errors early, (2) az deployment validate in the dev stage to confirm ARM acceptance, (3) az deployment what-if with a mandatory approval gate before any production target, (4) az deployment create in production with operation-level logs captured and retention policy set. All stages use a service principal or managed identity with least-privilege RBAC.
Phrases That Signal Platform Engineering Maturity
- "I always run what-if before production deployments and treat unexpected deletions as a hard stop."
- "We use Azure Verified Modules as the baseline and extend with our own private registry for company-specific configurations."
- "The choice between Bicep and Terraform depends on the operating model, not personal preference."
- "I use symbolic references rather than string interpolation to ensure Bicep resolves dependencies correctly."
- "For secrets, parameters are marked @secure() and values are sourced from Key Vault references in the parameters file — never hardcoded."
- "Deployment failures at runtime go through the operations list command first, not guess-and-redeploy."
Summary
Strong Bicep interview answers combine syntax fluency with operational reasoning. Knowing param decorators and loop syntax is the baseline. What separates senior candidates is the ability to explain failure triage, module design rationale, deployment mode tradeoffs, and when Bicep is and is not the right choice. Practice the scenario-based questions until your answers reference real command names, resource types, and failure modes rather than generalised descriptions.