Skip to content
DECLARE OR DRIFT

Bicep

Bicep for Azure

Bicep is how you author Azure-native deployments without hand-writing ARM JSON. Learn it by focusing on scopes, modules, parameters, outputs, existing resources, and what-if.

The problem

Bicep is Azure's native infrastructure language. It exists because ARM JSON is the deployment contract, but it is painful to author directly. Bicep gives you a cleaner language that compiles to ARM templates.

Do not think of Bicep as Terraform with different syntax. Bicep does not use Terraform state. It leans into Azure's deployment engine, scopes, what-if, and resource provider behavior.

  • Bicep is Azure-native.
  • ARM is the underlying deployment model.
  • No Terraform state file exists in the middle.

Vocabulary

Bicep files contain resources, parameters, variables, outputs, modules, and references to existing resources. Parameters are supplied at deployment time. Outputs expose values after deployment. Modules let one Bicep file call another.

Scope is central. A deployment can target a resource group, subscription, management group, or tenant. If you are unsure what scope you are deploying to, stop and resolve that before writing more code.

  • Parameter: value supplied by caller or environment.
  • Variable: computed value inside the file.
  • Resource: Azure object to deploy or configure.
  • Existing resource: object you reference but do not create.
  • Module: reusable deployment unit.

How the loop works

The Bicep loop is compile, what-if, deploy. What-if previews Azure changes before deployment. Deployment records then live in Azure, which can be useful for teams that want native Azure audit and operations behavior.

Existing resources are important for confidence. They let you reference a resource that already exists, such as a Key Vault or virtual network, without pretending your file owns its lifecycle.

  • `az bicep build` compiles to ARM JSON.
  • `az deployment group what-if` previews resource group changes.
  • `existing` marks a reference, not a creation.
  • Deployment stacks can help manage lifecycle and deletes for grouped resources.

Common mistakes

Do not choose Bicep or Terraform based on syntax preference alone. Choose based on operating model. Bicep is a good fit when the system is Azure-only and you want native Azure deployment behavior. Terraform is a good fit when Azure is one part of a larger multi-provider graph.

Another trap is underestimating scope. Subscription-level deployments can create role assignments, policies, and resource groups. That is powerful and easy to overreach.

  • Bicep usually gets new Azure resource support quickly.
  • Terraform has a larger cross-provider ecosystem.
  • Scope mistakes are often more dangerous than syntax mistakes.

Working pattern

Use Bicep when your team is Azure-first, wants native deployment records, and does not need to compose many non-Azure platforms in the same graph. Use modules for real boundaries: network, identity, app host, monitoring, policy.

Use Terraform when you need one workflow to coordinate Azure with Cloudflare DNS, GitHub repositories, Datadog monitors, Stripe config, or other providers.

  • Azure-only platform team: Bicep is a strong default.
  • Multi-provider product team: Terraform is often simpler operationally.
  • Mixed org: it is valid to use both, but define ownership boundaries.

The Review

  • Can you explain why Bicep does not need Terraform state?
  • Does the team need Azure-native deployment records more than cross-cloud composition?
  • Are scopes explicit enough to avoid accidental tenant or subscription writes?
  • Would deployment stacks improve deletion and lifecycle control?