Where Infrastructure Comes From
When a team starts building an application, the first questions are almost always about code: which language to use, how to structure directories, how to run it on a local machine. Questions about infrastructure usually come later, sometimes only when the app needs to run somewhere other people can access.
This is where things get interesting. Infrastructure doesn't appear by itself. Servers, databases, networks, load balancers -- all of it needs to be created, configured, and connected. The simplest approach is doing it manually: log into a cloud dashboard, click buttons to create a server, pick the specs, wait for it to be ready. That works fine for one server. But it starts falling apart when you have multiple servers, when you need staging and production environments, or when something breaks and you have to rebuild everything from scratch.
The problem isn't just time. When infrastructure is created manually, there's no reliable record of what was actually built. Developer A might create a server with certain specifications, while Developer B creates another server with slightly different settings -- maybe because they forgot, maybe because the cloud dashboard changed its interface. These small differences can cause bugs that are hard to track down: the application runs fine in staging but fails in production, even though the code is identical.
Manual infrastructure is also hard to reproduce. If the team needs a new environment -- say, for QA testing or a client demo -- the whole process has to be repeated from scratch. Each time, there's a risk of skipping a step or misconfiguring a parameter. The larger the infrastructure grows, the wider the gap becomes between what you intended and what actually gets created.
Treating Infrastructure Like Code
A better approach is to treat infrastructure the same way you treat application code. Write it in text files that humans can read, store those files in a repository, and manage them with the same processes you use for regular code. These files define what's called the desired state -- the ideal condition you want for your infrastructure, complete with server specifications, disk sizes, firewall rules, and database connections.
With this approach, nobody has to remember manual steps or rely on someone's memory. Every infrastructure definition lives in files that anyone on the team can see, review, and change. Changes to infrastructure go through the same pipeline as code changes: written, reviewed by teammates, and applied after approval.
Here is what a simple infrastructure definition looks like in Terraform:
resource "aws_instance" "app_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "ExampleAppServer"
}
}
This concept is called infrastructure as code, or IaC. The idea is straightforward: infrastructure isn't something you configure once and forget about. It's something you define, version, and manage throughout the life of your application. This way, you can be confident that staging and production environments are identical, that every change is traceable, and that you can spin up new environments anytime without worrying about missed steps.
Why Manual Infrastructure Fails at Scale
Let's make this concrete. Imagine your team manages ten servers manually. One day, a server crashes. You need to replace it. You log into the dashboard, create a new server, and try to remember what settings the old one had. Was it the same instance type? Did it have the same security group rules? Was the disk size the same? You might get it right, or you might not. And even if you do, there's no way to prove it.
Now imagine you need to create a completely new environment -- maybe for a performance testing team. You have to repeat every manual step from scratch. If your infrastructure has grown to include databases, load balancers, caching layers, and message queues, the manual process becomes a checklist that takes hours and is prone to human error at every step.
The real cost isn't the time spent clicking buttons. It's the uncertainty. When something goes wrong in production, you can't quickly answer questions like: "What changed in the infrastructure?" or "Is this environment configured exactly like staging?" Without infrastructure as code, those questions are hard to answer with confidence.
The Terraform Workflow Starts Here
This is where the Terraform workflow begins. Before running any commands, the team writes infrastructure definitions in configuration files. These files become the source of truth -- not the cloud dashboard, not personal notes, not someone's memory.
The workflow follows a simple cycle:
Write -- Define your infrastructure in configuration files. Describe the servers, networks, databases, and other resources you need.
Plan -- Ask Terraform to show you what will change before you apply it. This gives you a chance to review and catch mistakes.
Apply -- Execute the changes. Terraform compares your configuration against the current state of your infrastructure and makes only the changes needed to reach your desired state.
This cycle mirrors how you work with application code. You write code, review it, then deploy it. The difference is that instead of deploying application logic, you're deploying infrastructure definitions. And just like application code, these definitions live in version control, go through code review, and get tested before reaching production.
What Infrastructure as Code Changes
When you adopt infrastructure as code, several things shift in how your team operates:
Auditability becomes automatic. Every change to infrastructure is recorded in your version control history. You can see who changed what, when, and why. If a production issue appears, you can check whether infrastructure changes coincided with the problem.
Consistency becomes achievable. The same configuration file can create identical environments for development, staging, and production. Differences between environments become intentional and documented, not accidental.
Recovery becomes repeatable. If an environment gets corrupted or needs to be rebuilt, you don't need to remember manual steps. You run the same configuration files, and the infrastructure is recreated exactly as defined.
Collaboration becomes possible. Infrastructure definitions can be reviewed like code. Junior team members can learn by reading existing configurations. Senior team members can catch mistakes before they reach production.
A Practical Starting Point
If you're new to infrastructure as code, here's a simple checklist to get started:
- Pick one small piece of infrastructure you currently manage manually -- maybe a single server or a database instance.
- Write its configuration in Terraform or your IaC tool of choice.
- Run a plan to see what Terraform would change.
- Apply the configuration and verify the result matches what you expect.
- Commit the configuration files to your repository.
- Delete the manual resource and recreate it using only your configuration files.
This exercise proves to yourself and your team that the approach works. Once you've done it once, you'll start seeing other parts of your infrastructure that should be managed the same way.
The Takeaway
Infrastructure doesn't appear by magic, and it shouldn't be managed by memory. Writing infrastructure as code turns an error-prone manual process into a repeatable, reviewable, and auditable workflow. The Terraform workflow -- write, plan, apply -- is just a practical implementation of this idea. Before you run any command, start by defining what you want. That definition, stored in version control, becomes the single source of truth for your infrastructure. Everything else follows from there.