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.
New to cloud? CAMPUX is a free, build-first course. Start here →
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.
State. The tool needs some record of what it created, so it can tell the difference between "this resource is missing" and "this resource was never mine." Terraform keeps that record in an explicit state file. Azure's own tooling keeps it server-side, in the platform's deployment history, which is why Bicep has no state file to manage. Neither approach is free of consequences, and state is where most real-world infrastructure-as-code pain lives.
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 the most-requested skill in postings | Installing and configuring software on servers |
The Bicep-or-Terraform question has a boring answer: if the estate is Azure-only and likely to stay that way, Bicep is a genuinely nice experience — no state file to manage, new Azure features supported on day one, and a compiler that catches mistakes before deployment. If you are learning for the job market, learn Terraform, because it appears on far more postings and the concepts transfer to Bicep in an afternoon. Learning both is not twice the work; the second one is mostly vocabulary.
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?
Terraform if you are learning for the job market, because it appears on far more postings and the concepts transfer to Bicep in an afternoon. Bicep if the estate is Azure-only and staying that way, since it has no state file to manage and supports new Azure features on day one. Learning both is not twice the work; the second is mostly vocabulary.
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.