Infrastructure as code on Azure: from the concept to your first Terraform run
Clicking through the portal works right up until a second person touches the same environment. This is what replaces it: the three concepts tutorials skip, where Bicep and Terraform and Ansible each belong, and a six-week path to a Terraform setup that survives contact with other people.
Infrastructure as code means describing the environment you want in files, and letting a tool make reality match. On Azure that is Bicep if you are Microsoft-only and Terraform if you are not, both declarative, both idempotent, and both keeping some record of what they built. The skill that gets you hired is not the syntax — it is understanding desired state, idempotency and state files, because that is what separates a tutorial from a system two people can share.
Why clicking through the portal stops working
Nothing is wrong with the portal for one person learning one thing. It stops working for a specific reason: nothing you did is written down. Six months later nobody knows whether that firewall rule was deliberate, the staging environment has quietly drifted from production, the person who built it has left, and rebuilding it identically after an outage is a guessing game.
| Doing it in the portal | Doing it as code |
|---|---|
| Forty clicks, undocumented | A file in a repository, reviewable in a pull request |
| Different every time a person does it | Identical every time, on every environment |
| No history of who changed what, or why | Full history, with a commit message and an author |
| Staging drifts from production silently | Same files, different parameters — drift is visible |
| Rebuilding after a disaster is archaeology | Rebuilding is a command |
The three concepts tutorials skip
Most beginner material teaches syntax and skips the ideas underneath, which is why people can write a template and still not understand what happened when it misbehaves.
Declarative versus imperative. An imperative script is a list of steps: create this, then that, then the other. A declarative file is a description of the end state: this is what should exist. You do not tell it how, and you do not write the "does it already exist?" checks — the tool works out the difference between what you described and what is there. Nearly all modern infrastructure tooling is declarative, and it is the single biggest mental shift coming from scripting.
Idempotency. Running the same file twice produces the same result as running it once. That sounds like a technicality and it is the whole reason this works: you can apply on every commit without wondering whether you are about to create a second copy of everything. A script that is not idempotent is a thing you run nervously; a declarative file is a thing you run constantly.
Terraform keeps resource mappings in an explicit state file. Bicep compiles to ARM templates and does not require a Terraform-style client state file; Resource Manager evaluates deployments against Azure resource state. Deployment history is useful evidence, but it is not the same kind of ownership database as Terraform state. Incremental ARM deployment also does not delete every resource you omit from a template.
Which tool, on Azure
| Bicep | Terraform | Ansible | |
|---|---|---|---|
| Primary job | Provision Azure resources | Provision infrastructure, any cloud | Configure what runs on the machines |
| Category | Infrastructure as code | Infrastructure as code | Configuration management |
| Language | Bicep, which compiles to ARM JSON | HCL, declarative | YAML playbooks, task-based |
| State | Server-side, in Azure | An explicit state file you manage | None — it checks live state each run |
| Best at | Azure-only estates, day-one Azure support | Multi-cloud, and A provider ecosystem for Azure and other platforms | Installing and configuring software on servers |
For an Azure-only estate, Bicep offers close integration with ARM and no client state file to manage. Terraform brings its provider ecosystem and explicit state workflow. When learning for a job, inspect the actual roles you are targeting rather than assuming one tool wins every market. Verify the API versions and features you need in either tool; neither the language nor a template guarantees a safe deployment.
Ansible is not competing with either, and the argument only exists because both get called "infrastructure as code" loosely. Terraform builds the server; Ansible installs and configures what runs on it. The mature pattern uses both, and on a modern cloud estate the Ansible half often shrinks to nothing because the machines are immutable and replaced rather than configured in place. If you are choosing what to learn first, learn Terraform first — provisioning is the part a cloud role screens for.
A six-week path to a Terraform setup that survives other people
Syntax tours teach you to write a resource block and leave you helpless the first time state gets out of sync. This sequence is built the other way round, so each week ends with a concept that actually lands.
| Week | You build | The concept that lands |
|---|---|---|
| 1 | Provider setup, a resource group and a storage account, the plan-and-apply loop | Desired state, and reading a plan line by line |
| 2 | Change things on purpose: tags, names, sizes. Destroy and rebuild. | Update in place versus destroy and recreate — and which changes force which |
| 3 | Remote state in Azure Storage, migrating local state up, versioning on | State is shared memory, and locking exists for a reason |
| 4 | Variables, per-environment values, outputs — still flat files | Parameterize before you abstract |
| 5 | A pipeline: plan on a pull request, apply on merge, federated login | The pipeline is your loop with a review in the middle |
| 6 | The mess, on purpose: a rename, drift made in the portal, an import | Production work is state operations, not syntax |
Tutorial Terraform is writing resource blocks. Production Terraform is state operations — moves, imports, drift, and locking.
Two of those weeks deserve emphasis. Week three is where most people stop and should not. Local state works perfectly until a second person runs an apply, at which point two machines hold two different ideas of reality and one of them is about to destroy something. Remote state with locking is not an advanced topic; it is the first thing that makes this a team tool rather than a personal one.
Week four is where people over-engineer. The instinct after a fortnight is to build modules for everything. Resist it. Flat files with variables carry you a long way and stay readable, and a premature module layer is harder to debug than the duplication it removed. Parameterize first; abstract when the duplication actually hurts.
What it looks like in practice
The loop is short and you will run it hundreds of times. You write or edit a file describing what should exist. You ask the tool what it would change — the plan — and you read it, line by line, because that output is the last chance to notice something is about to be replaced rather than updated. Then you apply, and the tool makes reality match the file.
The single habit that separates a careful engineer here is reading the plan properly. A change that says it will destroy and recreate a database is a very different Tuesday from one that updates a tag, and both look like a successful apply afterwards. Everything else about this discipline is downstream of taking that output seriously.
If you are building a portfolio, infrastructure as code is the thing that repays the effort most. It is the line on nearly every mid-level posting, it is the difference between someone who administers a cloud and someone who engineers it, and it is inspectable — a hiring manager can open your repository and see whether you understand what you built. A screenshot of a portal proves nothing. A repository with a clean plan, remote state and a pipeline is evidence.
Questions people also ask
What is infrastructure as code in simple terms?
Describing the environment you want in files, and letting a tool make reality match. Instead of clicking through a portal and remembering what you did, you write down what should exist, keep it in version control, and apply it. The result is repeatable, reviewable and rebuildable, which is what makes it work once more than one person is involved.
Should I learn Bicep or Terraform for Azure?
For an Azure-only estate, Bicep offers close integration with ARM and no client state file to manage. Terraform brings its provider ecosystem and explicit state workflow. When learning for a job, inspect the actual roles you are targeting rather than assuming one tool wins every market. Verify the API versions and features you need in either tool; neither the language nor a template guarantees a safe deployment.
What is the difference between Ansible and Terraform?
Terraform provisions infrastructure — it creates the servers, networks and cloud resources. Ansible configures what runs on them — installing packages, editing configuration, deploying an application. They are complementary rather than competing, and the mature pattern uses both, though on a modern estate with immutable machines the configuration-management half often shrinks to very little.
What is Terraform state and why does it matter?
It is the record of what Terraform created, so it can tell the difference between a resource that is missing and one that was never its responsibility. It matters because it is shared memory: local state works until a second person applies, at which point two machines hold two versions of reality. Remote state with locking is what turns this from a personal tool into a team one, and most real-world pain lives in state operations rather than syntax.
Is Bicep infrastructure as code?
Yes. Bicep is Azure's own declarative language, compiling to the underlying template format, and it does everything the definition asks for: the environment is described in files, kept in version control, and applied repeatably. Its distinguishing feature is that the platform keeps the deployment record server-side, so there is no state file for you to store or lock.
What does idempotent mean in infrastructure as code?
Running the same file twice produces the same result as running it once. That is what makes it safe to apply on every commit — you are describing an end state rather than issuing commands, so the tool works out the difference and does nothing when there is nothing to change.
Every class is open to read. A free account saves your progress. Azure resources used for labs may incur charges.
It worked for them.
Sources and review
Reviewed 1 October 2026. The tool comparison distinguishes Terraform state from ARM deployment history. Choose from actual workload and hiring requirements rather than an unsourced job-market ranking.