Write Infrastructure as Code Before You Click Another Button
You have an application that needs a server and a database. The usual approach is to log into your cloud provider's dashboard, click through a few pages, select instance types, configure storage, set up networking, and hope you didn't miss any step. When you need to do it again for staging, you repeat the whole process. When a team member asks what infrastructure is running in production, you send them screenshots.
This workflow works until it doesn't. One missed checkbox, one wrong region selection, one forgotten security group rule, and your application either fails to run or runs with a vulnerability you didn't intend.
There is a better way: write your infrastructure as code.
What Infrastructure as Code Actually Means
Infrastructure as Code (IaC) is the practice of defining your servers, databases, networks, and other cloud resources in text files instead of clicking through a UI. These files describe the desired state of your infrastructure. You store them in version control, review them like application code, and apply them consistently across environments.
The key insight is that you are not writing a script that says "step one, create a server, step two, wait, step three, create a database." Instead, you declare what you want the final state to be. The tool figures out the order of operations based on dependencies between resources.
Writing Your First Configuration
Terraform is one of the most widely used IaC tools. You write configuration files with the .tf extension. Each file declares the resources you need and how they connect.
Start with a file called main.tf. The first thing to define is the provider. A provider is a plugin that lets Terraform talk to a specific platform like AWS, Google Cloud, or Azure. It tells Terraform where to create resources and what credentials to use.
provider "aws" {
region = "ap-southeast-1"
}
Once the provider is set, you define resources. Every resource follows this pattern: resource "type" "local_name". The local name is only used inside your configuration. It is not the name that appears in your cloud provider's console.
Here is how you create a virtual server, which AWS calls an EC2 instance:
resource "aws_instance" "app_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "app-server"
}
}
And here is a PostgreSQL database using RDS:
resource "aws_db_instance" "app_database" {
allocated_storage = 20
engine = "postgres"
engine_version = "15"
instance_class = "db.t3.micro"
db_name = "myapp"
username = "admin"
password = var.db_password
skip_final_snapshot = true
}
Notice something important: you did not write steps. You did not say "create the server first, then wait for it to be ready, then create the database." You declared what you want. Terraform analyzes the configuration, figures out that the database does not depend on the server, and creates them in parallel. If one resource depends on another, Terraform handles the ordering automatically.
Why This Feels Heavier at First
Writing configuration files takes more time upfront than clicking through a dashboard. You need to know the exact resource types, their required arguments, and how to structure the files. The dashboard shows you dropdown menus and checkboxes. The configuration file expects you to know what ami-0c55b159cbfafe1f0 means or what db.t3.micro refers to.
But this upfront cost pays off the moment you need to replicate the setup. Want a staging environment that mirrors production? Copy the files, change a few values, and run the same configuration. Want to understand what infrastructure is running? Read the files instead of hunting through the console. Want to review a change before it happens? Open a pull request and let your team comment on the diff.
Store Configuration in Version Control
Your .tf files should live in a Git repository. This can be the same repository as your application code or a separate infrastructure repository. Either way, every change to infrastructure goes through the same workflow as code changes: write, commit, review, merge, apply.
This gives you several benefits:
- Every infrastructure change is recorded with who made it and why.
- You can roll back to a previous state if something goes wrong.
- New team members can see the full infrastructure setup by reading the repository.
- Automated checks can validate the configuration before it reaches production.
What You Are Not Doing
When you write infrastructure as code, you are not writing a deployment script. A script runs commands in sequence. If step three fails, the script stops, and you have a partially created infrastructure. IaC tools like Terraform are declarative. They compare the current state of your infrastructure against the desired state in your configuration and make only the changes needed to reach that state.
This difference matters when you need to update infrastructure. Instead of writing a new script that accounts for the current state, you update the configuration file. Terraform figures out what to add, change, or remove.
The Practical Workflow
The typical workflow for Terraform has three phases: write, plan, apply.
First, you write or modify your .tf files. This is where you define the infrastructure you want.
Second, you run terraform plan. This command shows you what Terraform will do without actually doing it. It prints a detailed diff: which resources will be created, which will be modified, and which will be destroyed. You review this plan before proceeding.
Third, you run terraform apply to execute the plan. Terraform makes the API calls to your cloud provider to create, update, or delete resources until the actual state matches your configuration.
A Quick Checklist for Your First IaC Setup
- Choose a cloud provider and install the Terraform CLI.
- Create a
main.tffile with your provider block. - Define at least one resource, like a virtual machine or a database.
- Run
terraform initto download the provider plugin. - Run
terraform planto see what will be created. - Run
terraform applyto create the resources. - Store all
.tffiles in a Git repository and push them.
The Real Value Shows Up Later
Writing infrastructure as code feels like extra work on day one. On day thirty, when you need to add a new environment or recover from a mistake, it feels like the only sane way to work. The configuration files become the single source of truth for your infrastructure. No more guessing what is running in production. No more manual steps that someone might forget. No more infrastructure that only one person knows how to recreate.
Start with one resource. Write it in a file. Put it in Git. Then add the next resource. The habit builds faster than you expect, and the confidence it gives you is worth the initial friction.