Skip to content

Infrastructure as Code & Provisioning

Infrastructure as Code (IaC) defines cloud infrastructure in version-controlled, machine-readable files instead of manual console clicks, so environments are repeatable, reviewable, and auditable.

  • What it is: tools like Bicep, Terraform, or ARM/CloudFormation templates that describe infrastructure declaratively, deployed through a pipeline rather than a person clicking through a portal.
  • Why it matters: manual changes drift silently between environments until “works on staging, breaks in prod” becomes routine — IaC makes environments reproducible and changes reviewable.
  • For developers: if you can’t answer “what changed and who approved it” for a piece of infrastructure, it probably wasn’t provisioned through IaC.
  • When to use it: for any environment beyond a disposable personal sandbox.
  • When not to use it: a genuinely throwaway individual experiment may not need full pipeline rigor — but promote it to IaC before anything depends on it.
  • Prerequisites: Landing Zone Design.
graph LR
    Code["IaC files in source control"] --> PR["Pull request + review"] --> Pipeline["CI/CD pipeline"] --> Deploy["Deployed infrastructure"]
    Deploy -.drift detected.-> Code
  1. Choose an IaC tool consistent with the platform (e.g., Bicep for Azure-only, Terraform for multi-cloud).
  2. Model the landing zone and workload infrastructure as code, stored in source control.
  3. Require changes to flow through pull requests and a pipeline, removing direct console/CLI access to production where possible.
  4. Add drift detection so out-of-band manual changes are surfaced, not silently tolerated.
  5. Treat infrastructure changes with the same review rigor as application code changes.

Northwind’s logistics team’s environments have quietly diverged — someone tweaked a firewall rule in the portal here, resized a VM there — and nobody can say for certain what’s actually deployed anymore.

  • Input: infrastructure originally provisioned by hand, now drifted across environments with no change history.
  • Process: the team reverse-engineers the current state into Terraform/Bicep, removes standing console/CLI write access for individual engineers, and routes all future changes through pull requests and a pipeline; a drift-detection job runs nightly and flags any resource that no longer matches the code.
  • Output: within a few weeks, the drift-detection job catches and reverts an accidental manual change before it causes an incident, and every infrastructure change afterward has a reviewable pull-request history.
resource plan 'Microsoft.Web/serverfarms@2023-12-01' = {
name: 'checkout-plan'
location: location
sku: {
name: 'P1v3'
tier: 'PremiumV3'
capacity: 2
}
}
resource webApp 'Microsoft.Web/sites@2023-12-01' = {
name: 'checkout-web'
location: location
properties: {
serverFarmId: plan.id
httpsOnly: true
}
}

This is the actual Bicep behind the pull-request-reviewed pipeline in the example above — checked into source control, so the drift-detection job has something authoritative to compare the live App Service against.

Use case When to use Notes
Standing up a new environment identical to an existing one Reuse the same IaC module/template Environments genuinely match instead of “close enough”
Auditing what changed before an incident Read the IaC pull-request history Faster root-cause than reconstructing portal click history
Removing standing admin access to production Route all changes through IaC pipelines Reduces both accidental and malicious out-of-band changes
  • Declarative IaC (Bicep/Terraform) describes the desired end state; the tool computes the diff. Imperative scripting describes steps to take — declarative is generally preferred for infrastructure because it’s idempotent by default.
  • State files (Terraform) or deployment history (Bicep/ARM) must themselves be protected and backed up — losing track of state is its own outage risk.
  • Modules/reusable templates for common patterns (landing zone, network, standard VM) reduce copy-paste drift between teams.
Term Meaning
IaC Defining infrastructure in version-controlled, machine-readable files
Declarative Describes the desired end state; the tool computes how to get there
Drift When actual infrastructure no longer matches the code that should define it
State file Terraform’s record of what it believes is currently deployed
Module / template A reusable, parameterized IaC package for a common pattern
Symptom Likely cause Fix
“Works in staging, breaks in prod” despite supposedly identical environments Environments were provisioned manually and have drifted apart Reprovision both from the same IaC module/template
Nobody can say who changed a piece of infrastructure or why Manual console/CLI changes bypassing IaC Remove standing write access; require changes through pipeline + pull request
Terraform plan shows unexpected changes on every run Drift from manual out-of-band changes Import the actual state or revert the manual change, then re-run
  • Why is declarative IaC generally preferred over imperative scripts for infrastructure?
  • If a pipeline is the only way to change production, what should happen to “quick manual fixes” during an incident?

Part of Introduction to Cloud & Infrastructure Architecture. See also Landing Zone Design, Cloud Service & Deployment Models, Infrastructure Observability & Monitoring, and the Glossary.