Terraform 101: Infrastructure as Code Done Right

Terraform 101: Infrastructure as Code Done Right

A five-person startup signs its biggest customer yet. The contract has one condition: the customer wants its own isolated copy of the product, in a separate cloud account, ready in three weeks. Easy, says the CTO. Production already works. Just build another one.

Then the team opens the AWS console and realizes nobody remembers how production was built. The engineer who set it up left last spring. Nobody knows which load balancer settings were changed on purpose. There's a firewall rule called "temp-fix-do-not-delete" that nobody dares to touch. Three weeks turn into five, mostly spent clicking through screens and guessing.

This is the exact problem Terraform was built to fix. Instead of building servers, networks and databases by hand, you describe them in text files. Those files become the readable record of what exists. Want a second copy? Run the same files against a new account. Want to know what changed last Tuesday? Check the file history.

This guide covers what the tool does, how a run works, where it breaks, how it behaves as a team grows, and how to decide if it fits your business.

What Terraform actually does

Terraform is a free command-line tool, first released by HashiCorp in 2014, that creates and manages cloud resources from configuration files. Those files are written in HCL (HashiCorp Configuration Language), a format designed to be easy for people to read. A file might say "I want a storage bucket called monthly-reports in the Mumbai region," and Terraform takes care of the API calls needed to make that true.

This approach is called infrastructure as code. "Infrastructure" means the computing pieces your app runs on: servers, databases, networks, storage, DNS records, user permissions. "As code" means you manage those pieces through files that live in version control, the same way developers manage application code. Every change gets reviewed, recorded and can be undone.

A good way to picture the difference is cooking. Clicking around a cloud console is like cooking a family recipe from memory. It works, but no two batches come out quite the same, and when the cook leaves, the recipe leaves too. A Terraform file is the written recipe. Anyone on the team can follow it and get the same result.

Terraform is declarative, which means you describe the end result instead of writing steps. You don't say "first create a network, then add a server." You say "I want this network and this server," and Terraform works out the order. Delete the server from your file later, and Terraform removes it from the cloud.

Terraform talks to each service through plugins called providers: AWS, Azure, Google Cloud, and thousands more like Cloudflare, GitHub and Datadog. In March 2023, HashiCorp said its public registry had passed 3,000 providers and 12,000 reusable modules. That reach is a big reason teams pick Terraform IaC over single-vendor tools: one workflow can manage a database on AWS, DNS on Cloudflare and alerts in Datadog together.

THE NUMBERS BEHIND THE SHIFT

◆    Market size estimates disagree, and the gap is worth knowing about. Grand View Research valued the global infrastructure as code market at USD 1.02 billion in 2024 and projects USD 6.14 billion by 2033 (22.3% yearly growth). Global Market Insights puts 2025 at USD 1 billion, rising to USD 8.6 billion by 2035. P&S Intelligence estimates USD 1.3 billion for 2025 and USD 5.4 billion by 2032. The firms define the market differently, so treat these as a range, not a single answer.

◆    In the Stack Overflow 2025 Developer Survey, 17.8% of all respondents (and 18.7% of professional developers) said they had done extensive work with Terraform in the past year, compared with 11.7% for Ansible.

◆    Firefly's State of IaC 2025 survey found 89% of respondents had adopted IaC, yet only 6% had their whole cloud covered by code. 68% now run across more than one cloud.

◆    IBM completed its USD 6.4 billion acquisition of HashiCorp, the company behind Terraform, on February 27, 2025.

Those Firefly figures tell the real story. Almost everyone has started. Very few have finished. Most companies run a mix of coded resources and ones somebody clicked into existence years ago, and that mix causes most of the trouble covered below.

Six words you need before you start

Terraform has its own vocabulary. Learn these six terms and the rest of the documentation becomes much easier to follow.

Term

What it means

Everyday comparison

Provider

A plugin that lets Terraform talk to one service, such as AWS or GitHub

A translator who speaks one specific language

Resource

One thing Terraform manages: a server, a bucket, a DNS record

One item on a shopping list

State

A file where Terraform records what it has built and the real IDs of each item

The receipt that proves what you bought

Plan

A preview of what Terraform will create, change or delete before it does anything

A quote from a builder before work begins

Module

A reusable bundle of resources, such as "a standard web server setup"

A meal kit with ingredients already grouped

Backend

The place where the state file is stored, such as a cloud bucket

The filing cabinet where the receipts live

How a Terraform run works, step by step

Every Terraform tutorial starts with the same four commands, because nearly all daily work is built from them. Here they are in the order you'll use them.

The first is terraform init. It downloads the providers your files ask for and connects to wherever your state is stored.

The second is terraform plan. Terraform reads your files, checks the real cloud to see what currently exists, and prints a list of differences. Nothing gets changed at this stage. The output uses simple symbols: a plus sign means something will be created, a tilde (~) means something will be updated in place, a minus sign means something will be deleted, and "-/+" means something will be destroyed and rebuilt.

The third is terraform apply. Terraform shows the plan again, asks you to type "yes", and then makes the changes.

The fourth, terraform destroy, removes everything the configuration manages. It's useful for temporary test environments and dangerous anywhere else.

Here is a small but complete example. It tells Terraform to use the AWS provider in the Mumbai region and create one storage bucket.

terraform {

  required_providers {

aws = {

   source  = "hashicorp/aws"

   version = "~> 6.0"

}

  }

}

 

provider "aws" {

  region = "ap-south-1"

}

 

resource "aws_s3_bucket" "reports" {

  bucket = "acme-monthly-reports"

}

The line version = "~> 6.0" does real work. It accepts any 6.x version of the AWS provider and refuses 7.0. Major versions sometimes change how resources behave, and you don't want that surprise arriving because someone ran init on a new laptop.

Pro tip: apply exactly what you reviewed

Run terraform plan -out=tfplan, review the saved plan, then run terraform apply tfplan. Without the saved file, apply builds a fresh plan, and if anything in the cloud changed in between, you could approve one thing and get another. A saved plan removes that gap.

State: the file that makes or breaks your setup

If you only remember one section of this guide, make it this one. Most painful Terraform incidents trace back to the state file.

The state file is Terraform's memory. When Terraform creates a server, the cloud hands back an ID like i-0abc123. Your code never mentions that ID; it just says "a server called web." State links the two. Lose the state file, and Terraform forgets it built anything. Run apply again and it will try to build everything a second time.

By default, state is saved as terraform.tfstate on the laptop of whoever ran the command. That's fine for learning and a problem for any team. If two people run apply at the same moment against the same state, they can corrupt it.

The fix is a remote backend with locking, so only one person or pipeline can change state at a time. On AWS, teams used to need two services for this: an S3 bucket for the file and a DynamoDB table for the lock. Starting with Terraform 1.10, the S3 backend can lock using a small lock file stored right next to the state, and HashiCorp's documentation now marks DynamoDB-based locking as deprecated. A modern setup looks like this:

terraform {

  backend "s3" {

bucket    = "acme-terraform-state"

key       = "prod/network.tfstate"

region    = "ap-south-1"

encrypt   = true

use_lockfile = true

  }

}

There's a second, less obvious danger. The state file stores the full details of everything Terraform manages, and that can include database passwords and access keys in readable text. Treat the state bucket like a vault: encrypt it, turn on versioning so you can roll back a damaged file, and give access only to the people and pipelines that need it. Terraform 1.10 also added ephemeral values, which let some secrets pass through a run without ever being written to state. Where your provider supports them, use them.

Data gaps and conflicting signals

Here's where things get more interesting than beginner tutorials suggest. At any moment there are three versions of the truth: what your code says, what state remembers, and what actually exists in the cloud. When they disagree, you need to know which one Terraform trusts.

During a plan, Terraform first refreshes, asking the cloud about every resource in state. Then it compares that reality against your code and proposes changes to make reality match. The code wins. That sounds reasonable until you see what it means in practice.

Drift: when someone fixes things by hand

Drift is the name for changes made outside Terraform. A developer opens a firewall port in the console during an outage. A support engineer bumps a database size to handle a traffic spike. Nobody updates the code. The next time anyone runs plan, Terraform sees the difference and proposes to undo the fix, because the code still describes the old setup.

If the person running apply doesn't read the plan closely, the outage comes back. Firefly's surveys have tracked how common this is:

▪       In the 2024 survey, 40% of respondents said they could not detect drift at all, and 13% of the time drift was never fixed.

▪       In 2025, fewer than one-third of organizations monitored drift continuously; the rest found it only when something broke.

▪       In the 2026 report, one-third of respondents tied drift to a costly production incident, 8% said it caused significant downtime, and nearly 20% still had no process for detecting or fixing it.

The practical answer has two parts. First, run terraform plan -detailed-exitcode on a schedule. It exits with code 2 when it finds differences, which makes it easy to send an alert. Second, agree as a team on a rule: any manual change made during an emergency must be copied back into the code within a day.

Values Terraform can't know yet

A server's IP address doesn't exist until the server does. In a plan, such values show up as "(known after apply)." That's usually harmless, until you use one to decide how many resources to create. Terraform can't plan "one firewall rule per IP address" without knowing the addresses, so it stops with an error. Base those counts on values you define yourself, such as a list of names.

When the cloud gives slow or mixed answers

Cloud APIs are not always instant. On AWS, a newly created permission role can take a few seconds to become visible everywhere. Terraform creates the role, immediately tries to use it, and the cloud replies that it doesn't exist. Run apply again a minute later and it works. Providers retry many of these cases, but not all. An error that vanishes on the second run usually has this cause.

Two tools fighting over one setting

Some settings are meant to change on their own. An autoscaler raises the server count when traffic climbs, and if Terraform also manages that number, every plan tries to reset it. The ignore_changes setting tells Terraform to leave specific attributes alone. Add a comment explaining why, because a future teammate may not guess.

Decisions you make in the middle of an apply

Terraform has no automatic rollback. That surprises a lot of people. If an apply creates eight resources and the ninth fails, the first eight stay. Terraform saves them in state, reports the error and stops.

That leaves you with a live decision, often under time pressure. The calm path is to fix the cause, then run plan again and read it. Since state already knows about the eight successful resources, the new plan should show only the remaining work. Don't delete things by hand to "get back to clean." That creates a new mismatch between state and reality.

Replacements need special care. Some settings can't be changed on a live resource; changing them forces Terraform to destroy the old one and build a new one. For a web server, that might mean a few minutes of downtime. Adding create_before_destroy tells Terraform to build the replacement first and remove the old one only after the new one is ready.

For anything you can't afford to lose, such as a production database, add prevent_destroy. With it in place, any plan that would delete that resource fails outright, even if someone approves it by mistake.

Pro tip: read the plan from the bottom up

The last line of every plan shows a summary, such as "Plan: 2 to add, 1 to change, 1 to destroy." Read that line first. If you expected zero deletions and see one, stop and find out why before you look at anything else.

Edge cases that catch new teams

These come up in nearly every team's first year.

▪       Renaming a resource in code looks harmless, but Terraform sees a deleted resource and a new one. It will destroy and rebuild. Since version 1.1, a moved block tells Terraform "this is the same thing with a new name," and nothing gets touched in the cloud.

▪       Using count to create several similar resources ties each one to a position number. Remove the second item from a list of five, and items three, four and five all shift position, so Terraform rebuilds them. Using for_each with names instead of positions avoids the shuffle.

▪       Resources created by hand before Terraform arrived are invisible to it. Since version 1.5, import blocks let you bring them under management. Write the configuration, import the resource, then run plan and keep adjusting until it shows no changes.

▪       Upgrading Terraform or a provider can change behavior. The .terraform.lock.hcl file records exact provider versions; commit it to version control so everyone uses the same ones.

▪       Changing the region in a provider block doesn't move anything. It points Terraform at a different place where none of your resources exist, and the plan will try to build everything from scratch.

How Terraform behaves at scale and under pressure

A project with 30 resources plans in seconds. A company with thousands of resources in one state file can wait minutes for each plan, and that slowness changes behavior. Engineers start skipping plans or making quick console fixes, which leads back to drift.

The slowdown has a clear cause. Every plan refreshes every resource in state, and each refresh is an API call. By default, Terraform runs ten operations in parallel. Cloud providers limit how many API calls an account can make per second, so a very large state can hit those limits, and the run slows down or fails with "rate exceeded" errors. You can change the parallelism setting, but the better fix is structural.

That fix is splitting state by blast radius. "Blast radius" means how much breaks if something goes wrong. Teams commonly keep separate states for the network, for shared data stores like databases, and for each application. A mistake in an application's configuration then can't touch the network everyone depends on. Smaller states also plan faster and lock less often, so two teams aren't stuck waiting on each other.

Splitting has a cost. The application needs the network's ID, which now lives in a different state. Teams pass values between states using outputs, and those links need documenting. Rename an output in the network project and every application reading it breaks on its next plan.

Firefly's 2026 report shows how many teams struggle here: 90% of respondents agreed their IaC orchestration falls short, and only 8% reported no notable scaling issues. At that size, Terraform IaC stops being a tool one engineer runs from a laptop and becomes a shared system that needs owners, conventions and a pipeline.

Pressure also shows up at 2 a.m. Production is down, the fix is one setting, and the pipeline takes fifteen minutes. Most experienced teams accept a console fix in that moment. Healthy teams differ in what happens next morning: someone copies the fix into code and confirms plan shows no changes. Skip that a few times and the code stops describing reality.

Putting Terraform into a team pipeline

Running Terraform from a laptop works for one person. Once a second person joins, the commands belong in a shared pipeline. This is where Terraform connects to wider DevOps automation: letting software handle the repeatable steps of building, testing and releasing.

A typical flow looks like this:

1.      A developer changes a Terraform file on a branch and opens a pull request.

2.      The pipeline runs terraform fmt -check and terraform validate to catch formatting and syntax mistakes.

3.      A security scanner such as Checkov or Trivy reviews the code for risky settings, like a storage bucket open to the public.

4.      The pipeline runs plan and posts the output as a comment on the pull request, so reviewers see exactly what will change.

5.      A teammate reviews both the code and the plan, then approves.

6.      After merge, the pipeline applies the saved plan using its own cloud credentials. Individual engineers no longer need production access for routine work.

Step three matters more than it looks. In a February 2019 report, Gartner predicted that through 2025, 99% of cloud security failures would be the customer's fault, with misconfiguration the classic cause. When settings live in code, a scanner can flag an open database port before it ships. When they live in the console, the first warning often comes from an attacker.

Larger teams add policy checks with HashiCorp's Sentinel or the open-source Open Policy Agent, enforcing rules like "every resource must have an owner tag."

AI agents are joining these pipelines too. Firefly's 2026 report found 44% of respondents running AI for infrastructure automation in production or pilots, yet only 34% would let an agent make production changes on its own, and 42% named missing guardrails as the main blocker. Treat an AI agent like a new hire: it opens pull requests, its plans get reviewed, and it never holds credentials that can delete production unapproved.

How Terraform compares with the alternatives

Terraform isn't the only option, and it's worth knowing what else exists before committing.

Tool

How you write it

License

Clouds supported

Best suited for

Terraform

HCL configuration files

Business Source License 1.1

Almost any, through providers

Teams wanting the largest ecosystem and hiring pool

OpenTofu

HCL, compatible with Terraform

Mozilla Public License 2.0 (open source)

Same provider ecosystem

Teams that want Terraform's model under an open-source license

Pulumi

Python, TypeScript, Go, C#, Java or YAML

Apache 2.0

Most major clouds

Developer-heavy teams who prefer a real programming language

AWS CloudFormation

JSON or YAML templates

Proprietary AWS service

AWS only

Companies fully committed to AWS that want AWS to hold state

Ansible

YAML step-by-step playbooks

GPL v3

Many, but focused on configuring servers

Installing and configuring software on machines that already exist

The licensing row needs explaining, because it changed in a way that still shapes decisions today. Terraform was open source under the Mozilla Public License for nine years. On August 10, 2023, HashiCorp moved Terraform and its other products to the Business Source License. For most companies using Terraform to run their own systems, daily life didn't change. The restrictions target businesses offering products that compete with HashiCorp's own commercial services. If you're building a hosted infrastructure product, have a lawyer read the license.

A group of vendors forked the last open-source version, Terraform 1.5.7, and the Linux Foundation accepted the project, renamed OpenTofu, on September 20, 2023. OpenTofu reads the same files and uses the same providers, and has added features of its own, such as built-in state encryption. The projects are slowly diverging, so switching gets a little harder with each release.

Terraform and Ansible are often treated as rivals, but many teams use both. Terraform builds the house. Ansible furnishes it, installing software inside the servers. Firefly's 2025 survey still found most IaC users on Terraform, though it noted that lead was narrowing.

Is Terraform right for your team?

Terraform takes effort. Someone has to learn it, set up state storage and build a pipeline. Whether that pays off depends on what you run.

Your situation

Recommendation

Why

One app on a fully managed platform like Vercel or Heroku

Wait

Little infrastructure to manage; the platform already does the work

A startup on AWS, Azure or Google Cloud with a few services

Start now

Cheapest moment to adopt; small setups are easy to codify

Multiple environments (dev, staging, production)

Start now

Keeping environments identical by hand rarely works for long

Customers asking about security audits or compliance

Start now

Code history gives auditors a record of every change and approval

A large existing setup built entirely by hand

Start gradually

Import the most critical pieces first; codifying everything at once stalls

For founders, the strongest case isn't speed. It's that knowledge stops living in one person's head. For office teams and operations staff, Terraform IaC means requests like "we need a new environment for the training team" can become a reviewed pull request instead of a week of manual setup.

There's also a hiring angle. In the Stack Overflow 2025 survey, 51.8% of developers who used Terraform said they want to keep using it, and a familiar tool makes it easier to hire people productive from day one.

A sensible first month with Terraform

Reading only gets you so far. Here's a four-week plan for a solo developer or a small team. Treat it as a hands-on Terraform tutorial you run against your own account.

1.      Week one: Install Terraform, create a separate test account in your cloud provider, and build something small and cheap, such as a storage bucket. Run plan, apply and destroy until the cycle feels normal.

2.      Week two: Set up a remote backend with encryption, versioning and locking. Move your test project to it. Then make a change in the console on purpose and watch how plan reports the drift.

3.      Week three: Import one real but low-risk resource from your production account, such as a DNS record. Adjust your code until plan shows no changes. That "no changes" result is your goal for every resource you bring in.

4.      Week four: Put the project into your code repository and set up a basic pipeline: format check, validate, plan on pull requests, apply on merge. This is your first piece of real DevOps automation, and every resource you add from here gets reviewed automatically.

After that, add one area at a time. Networks and DNS change rarely and make good early candidates. Bring databases in last, with prevent_destroy in place.

Key takeaways

✓    Terraform lets you describe cloud setups in readable files, so your infrastructure is reviewed, recorded and repeatable.

✓    The state file is Terraform's memory. Store it remotely, encrypt it, version it and lock it from day one.

✓    Drift is the most common source of trouble. Detect it on a schedule and copy every emergency fix back into code.

✓    At scale, split state by blast radius and move every apply into a reviewed pipeline.

✓    Terraform's license changed in 2023. OpenTofu is the open-source fork, and both use the same configuration language.

Conclusion

The startup from the opening didn't have a cloud problem. It had a memory problem. Its production setup lived in one former employee's head.

That is what infrastructure as code fixes, and Terraform remains the most widely used way to do it. The tool itself is approachable: a handful of commands and a configuration format most people can read after an afternoon. The harder lessons sit around it. Guard the state file. Watch for drift. Read every plan. Split things up before they get big. Put changes through a pipeline instead of a laptop.

None of that needs a large team. It needs small steps and good habits, built while your setup is still simple, with DevOps automation handling the repeatable parts. Write down your infrastructure now, and the next big customer request becomes a pull request instead of a five-week scramble.

Prachi Singh

Prachi Singh

Prachi, our dedicated Digital Marketing Manager! With industry experience and expertise, she elevates our online presence and expands our reach. Prachi's eye for detail and data-driven insights help her formulate result-oriented marketing strategies. Her efforts consistently boost our business visibility and contribute significantly to our ongoing success.

Build Your Agile Team

We provide you with a top-performing extended team for all your development needs in any technology.

Hourly
$20
It Includes
Duration
Hourly Basis
Communication
Phone, Skype, Slack, Chat, Email
Hiring Period
25 Hours (MIN)
Project Trackers
Daily Reports, Basecamp, Jira, Redmime, etc
Methodology
Agile
Monthly
$2600
It Includes
Duration
160 Hours
Communication
Phone, Skype, Slack, Chat, Email
Hiring Period
1 Month
Project Trackers
Daily Reports, Basecamp, Jira, Redmime, etc
Methodology
Agile
Team
$13200
It Includes
Team Members
1 (PM), 1 (QA), 4 (Developers)
Communication
Phone, Skype, Slack, Chat, Email
Hiring Period
1 Month
Project Trackers
Daily Reports, Basecamp, Jira, Redmime, etc
Methodology
Agile

Frequently Asked Questions

Do I need to know how to code to use Terraform?
Not in the way an app developer does. HCL reads more like a settings file than a program, with names, values and some simple lists. If you can edit a spreadsheet formula, you can follow a basic Terraform tutorial. Understanding cloud concepts like networks and permissions matters more than programming skill.
Is Terraform still free to use?
The Terraform command-line tool can still be downloaded and used at no cost, including by companies managing their own systems. It's licensed under the Business Source License, which restricts using it to build products that compete with HashiCorp. HCP Terraform, the hosted service for teams, has paid plans. OpenTofu is a fully open-source alternative.
What's the difference between Terraform and Ansible?
Terraform creates and removes infrastructure like servers, networks and databases, and keeps a state file to track them. Ansible mainly configures what runs inside existing servers, using step-by-step instructions. Many teams use Terraform to build machines and Ansible to set them up.
What happens if someone changes something directly in the cloud console?
The next plan will notice and propose changing the setting back to match your code. If the manual change was an intentional fix, update the code first. Otherwise you may undo the fix without realizing it.
Should a startup choose Terraform or OpenTofu?
Both use the same file format and providers, so skills carry over. Terraform has the larger ecosystem, more training material and paid services backed by IBM. OpenTofu offers an open-source license under the Linux Foundation and built-in state encryption. If licensing matters to your business or investors, look closely at OpenTofu; otherwise, either works well for infrastructure as code at startup scale.