INSIGHTS
Cloud Computing

Microsoft AZ-400: Azure IaC with Bicep & Terraform

In this article
  1. Choose the tool from the infrastructure scope
  2. Understand the state model before scaling
  3. Use modules to create stable platform building blocks
  4. Preview changes before applying them
  5. Secure Terraform state and pipeline credentials
  6. Separate validation, preview, and deployment stages
  7. Detect drift without making every difference destructive
  8. Govern modules, repositories, and environments as products
  9. A mixed strategy can be better than a forced standard

Infrastructure as code is most valuable when it makes environmental change reviewable, repeatable, and recoverable. Azure teams commonly use Bicep or Terraform to describe desired infrastructure, but the two tools make different assumptions about scope, state, providers, and the deployment engine. The current AZ-400 objectives expect DevOps engineers to define an IaC strategy, automate testing and deployment, select configuration technologies, and implement desired state across Azure environments.

The decision should not begin with syntax preference. Start with the infrastructure estate, team operating model, existing modules, state-management requirements, cloud scope, and governance controls. Bicep is tightly aligned to Azure Resource Manager. Terraform uses providers and maintains state so it can manage Azure together with many other platforms. Both can be excellent when the surrounding delivery process is designed deliberately.

Choose the tool from the infrastructure scope

Bicep is an Azure-specific declarative language that compiles to Azure Resource Manager templates. It receives Azure resource capabilities directly through the Resource Manager model, uses symbolic references and modules, and does not require a separate state file. This makes it attractive for organizations whose infrastructure automation is primarily or entirely Azure.

Terraform is a general-purpose infrastructure-as-code tool. Azure deployments commonly use the AzureRM provider for stable Azure resources, AzAPI when direct Resource Manager coverage is useful, and other providers for Microsoft Entra, Azure DevOps, SaaS platforms, or non-Azure infrastructure. A single configuration can therefore coordinate resources across several APIs.

The broad infrastructure-as-code model matters more than allegiance to one tool. The objective is a controlled description of desired infrastructure with review, automation, validation, and reproducible deployment.

The AZ-400 perspective is less about memorizing a winner and more about designing a repeatable delivery process around infrastructure code. Source control, pull-request validation, policy checks, secretless deployment identity, environment protection, change previews, and post-deployment verification matter regardless of the language. The strongest choice is the one the organization can secure, review, operate, and upgrade consistently over time.

Understand the state model before scaling

Bicep relies on Azure Resource Manager and incremental deployment rather than maintaining a client-side state file that maps configuration to infrastructure. Azure itself is the source of current resource state for deployment processing. The Bicep what-if operation can preview expected resource changes before deployment.

Terraform maintains state that records the resources it manages and information needed to map configuration to real infrastructure. That state enables planning and lifecycle operations, but it becomes a critical asset. Teams must store it remotely for collaboration, protect access, back it up appropriately, and prevent secrets or sensitive outputs from leaking through the state file.

This difference affects incident recovery and operating ownership. A lost or corrupted Terraform state backend can disrupt infrastructure management even when Azure resources continue running. Bicep avoids that particular dependency, while Terraform gains the cross-provider mapping that makes it useful beyond Resource Manager.

Bicep deployments rely on Azure Resource Manager to evaluate desired resource declarations against Azure. Terraform maintains its own state representation so it can map configuration addresses to remote objects and calculate changes. That state is operationally important data. It should be stored in a controlled backend with appropriate access, locking, backup, and separation between environments. Treating Terraform state as an incidental file is one of the quickest ways to create unsafe collaboration and recovery problems.

Use modules to create stable platform building blocks

Large IaC repositories become difficult to reason about when every application defines networks, identities, diagnostics, and policy differently. Both Bicep and Terraform support modules that package reusable infrastructure patterns behind controlled inputs and outputs.

A good module hides implementation detail without hiding risk. A virtual-network module can standardize diagnostic settings and tagging while still exposing address ranges and connectivity options that consumers genuinely need to choose. An application module can provide approved defaults for managed identity, private endpoints, or monitoring without turning every platform decision into a hardcoded constant.

Version modules deliberately. Central reuse reduces duplication, but an unversioned module that changes under hundreds of deployments can create a new kind of instability. Publish tested versions, document breaking changes, and make upgrades visible through pull requests.

A module should represent an intentional platform capability rather than merely move lines into another file. Good modules expose a small set of meaningful inputs, choose secure defaults, return outputs that callers genuinely need, and hide implementation details that should remain consistent. Examples include a standard storage account with diagnostic settings, a private application environment, or a network segment with approved security controls. Version modules when callers need a stable contract across many repositories.

Preview changes before applying them

Infrastructure review should include the expected effect of the code, not only the code diff. Terraform plan produces an execution plan showing what it expects to create, update, or destroy. Bicep and Resource Manager support what-if to preview resource changes. Both techniques help reviewers catch unintended replacement, deletion, or scope changes before production deployment.

Make the preview part of the pull request workflow where practical. Reviewers should be able to see that a small code edit will replace a database, widen a firewall rule, or remove a diagnostic setting. The plan is not infallible, but it adds operational evidence that source review alone cannot provide.

Azure Policy provides another predeployment boundary. Bicep integrates directly with Resource Manager validation, and Terraform deployments can also be blocked when Azure Policy denies a noncompliant resource. Policy should complement IaC review by enforcing requirements that must hold even if a pipeline or human misses them.

For Bicep, validation and what-if can expose syntax, policy, and proposed Azure Resource Manager changes before deployment. For Terraform, formatting, validation, initialization, and plan create a similar pre-apply review path. The preview should be tied to the same source revision and configuration that will later deploy. Recomputing a materially different plan at approval time weakens the evidence reviewers thought they were accepting.

Approval evidence should also be readable. Large raw plans can bury the few changes that matter, so pipelines should summarize additions, updates, deletions, replacements, and sensitive-scope changes while retaining the complete preview for deeper review. The goal is not to hide detail but to help reviewers find the risky detail quickly. Policy evaluation can run alongside the preview so a change that violates mandatory controls fails before anyone spends time approving it.

Secure Terraform state and pipeline credentials

Terraform state can contain resource identifiers and sensitive values, so remote backends need encryption, restricted access, and carefully scoped pipeline identity. Azure Storage is a common backend choice for Azure workloads, but the design still needs authentication, authorization, locking behavior, backup, and lifecycle controls.

Do not put provider secrets in configuration files. Prefer managed identities or workload identity federation where supported. Separate plan-time and apply-time privilege if the operating model requires independent approval. The pipeline that reads a plan does not necessarily need authority to apply it to production.

The security concerns described in Terraform secrets-management practices extend beyond Terraform itself. Bicep pipelines also need protected service connections, Key Vault access, and least-privilege Azure roles. IaC changes can alter security boundaries, so deployment identities deserve the same scrutiny as application credentials.

Remote state can contain resource identifiers and, depending on providers and resource behavior, sensitive values. Encrypt it at rest, restrict access to the identities that need it, and avoid exposing state output in ordinary pipeline logs. Separate production state from development and test, and do not give every contributor direct write access to the backend. Recovery procedures should include restoring or reconciling state without blindly recreating live infrastructure.

Separate validation, preview, and deployment stages

A robust IaC pipeline does not jump from commit to production apply. It validates formatting and syntax, runs static analysis or policy checks, resolves modules, creates a preview, requires the appropriate review, and then deploys the approved revision. The stages may be simple for development environments and stronger for production.

Keep the deployment input stable between preview and apply. With Terraform, a saved plan can reduce ambiguity if the organization wants the approved plan to be the one applied. With Bicep, retain the exact source revision and parameter set that produced the reviewed what-if output. Avoid changing variables manually after approval.

The distinction between automation and orchestration is useful here. IaC code declares infrastructure, while the pipeline orchestrates when validation, approval, deployment, and verification happen across environments.

This separation creates faster feedback and clearer authority. Pull requests can run linting, policy checks, module tests, and change previews without production credentials. A protected deployment stage can then acquire the narrowly scoped identity required to apply an approved change. The pattern reduces the time privileged credentials are available and makes it easier to show which checks were completed before an environment was modified.

Detect drift without making every difference destructive

Out-of-band changes happen. Operators may respond to an incident in the portal, a service may change a managed property, or another automation system may update a resource. The IaC process needs to identify whether the difference is legitimate, temporary, or evidence that ownership is unclear.

Terraform uses state and refresh behavior to compare configuration with real infrastructure. Bicep deployments reconcile declared resources through Resource Manager, and what-if can reveal expected changes before deployment. In either model, blindly forcing every observed difference back to code can be dangerous if the team does not understand why the difference exists.

Define ownership for resource properties. Some settings may be managed by policy, autoscaling, security tools, or service controllers rather than IaC. Stable ownership reduces noisy drift and prevents two systems from continuously overwriting one another.

Drift can be legitimate, accidental, or malicious. An emergency configuration change may need to be imported back into code; a portal edit may need to be reverted; a provider default may simply be represented differently after an upgrade. The correct response starts with classification. Automated drift checks should create evidence and ownership, not immediately force every difference back to the repository when the cause is still unknown.

Govern modules, repositories, and environments as products

Infrastructure platforms scale through standards. Publish approved module libraries, naming conventions, tagging rules, diagnostic defaults, identity patterns, and network patterns. Protect the repositories that contain those standards because a change in a shared module can affect many subscriptions or applications.

AZ-104 administration knowledge remains relevant because the IaC layer ultimately creates resources that still need correct RBAC, networking, storage, monitoring, backup, and lifecycle configuration. Automation does not remove the need to understand the platform it controls.

Use environment-specific parameters sparingly. If production has hundreds of exceptions from the standard module, the organization may have hidden architectural divergence inside parameter files. Prefer a small number of well-understood differences and separate modules when workloads truly need different patterns.

Platform teams should publish supported versions, ownership, upgrade guidance, examples, and deprecation timelines for shared IaC. Consumers need to know how quickly security fixes will be delivered and how breaking changes are introduced. Repositories that create subscription-level or identity resources deserve stronger review than narrowly scoped application modules because their blast radius is larger. Governance should follow impact rather than applying identical friction everywhere.

Record tool and provider versions as part of the supported platform contract. Bicep language changes, Azure API versions, Terraform provider upgrades, and module revisions can alter plans even when application intent has not changed. Controlled upgrades with representative tests reduce surprise and make rollback easier when a new version produces unexpected infrastructure behavior.

A mixed strategy can be better than a forced standard

Some enterprises use Bicep for Azure-native platform components and Terraform for cross-cloud or SaaS resources. Others standardize on Terraform so one skill set spans providers. Still others choose Bicep because Azure is the dominant platform and direct Resource Manager alignment reduces state-management overhead. Each approach can be coherent.

The danger is unmanaged overlap. If Bicep and Terraform both believe they own the same resource properties, deployments can fight each other. Draw clear boundaries by subscription, resource group, module, resource type, or platform capability. Document where each tool is authoritative and how outputs cross from one automation domain to another.

A mature IaC strategy can therefore explain more than which language the team uses. It can explain how changes are reviewed, how previews are approved, where state lives, how identities authenticate, how modules are versioned, how drift is handled, and how the organization recovers from a bad infrastructure deployment. That operating model is what turns Bicep or Terraform from a scripting preference into dependable Azure delivery infrastructure.

Some organizations use Bicep for Azure-native platform components and Terraform where cross-provider orchestration or existing module investment makes it the stronger fit. That can work if boundaries are explicit. Avoid having two tools manage the same resource or overlapping properties, because ownership ambiguity produces persistent drift and difficult incident recovery. Define which repository and state model is authoritative for every managed object.

Standardize the surrounding lifecycle even when the languages differ. Both Bicep and Terraform repositories can use protected branches, peer review, automated validation, environment-specific identities, immutable pipeline artifacts, and post-deployment verification. A common governance model lets teams choose the tool suited to the resource boundary without creating two completely different security and operating practices.

Document ownership at resource boundaries so future teams know which tool is allowed to change each object. Clear ownership prevents an emergency fix in one system from becoming unexplained drift in another.

Filed under Cloud Computing