Explainer

Infrastructure as code with Terraform explained

Learn how Terraform turns cloud infrastructure into versioned code, how the plan and apply cycle works, and what to watch for.

By the Cloudverg engineering team · · 5 min read

What it is

Terraform is a tool that turns cloud infrastructure into files you keep in a repository. You describe the servers, networks, databases and DNS records you want, and Terraform works out the API calls to create or change them. The files are the source of truth. Nobody clicks through a console to build production, and nobody has to remember what was clicked last time.

The files use a language called HCL. It is small: blocks with a type and a name, and arguments inside. A provider block says which cloud to talk to and which version to use. A resource block names a thing, such as aws_s3_bucket, and gives it settings. Variables pass values in, outputs hand values back out, and modules group resources for reuse.

The part people underestimate is the state file. Terraform records what it built and maps each block in your code to a real object in the cloud. Every plan compares your code, that record and the live API. Lose the state and Terraform no longer knows what it owns, even though the infrastructure still runs and still bills you.

How it works

The loop is short. terraform init downloads providers and configures the backend. terraform plan reads your code and the live environment, then prints what it would do with markers for create, change and destroy. terraform apply runs the changes after you confirm. terraform destroy removes everything the state tracks, which is useful for test environments and dangerous everywhere else.

Treat the plan as a review artifact, not a formality. Read the whole thing, especially any line that says a resource will be replaced. Some argument changes force a rebuild, and a rebuild of a database or a load balancer means downtime. Add -out to save a plan file, then apply that exact file so what you approved is what runs.

Put state in a remote backend before a second person touches the repo. On AWS that usually means an S3 bucket with versioning and encryption, plus a DynamoDB table for locking so two applies cannot run at once. Hosted services such as HCP Terraform do the same job with a UI. Keep the backend configuration in the repo so nobody rebuilds it by hand.

Structure around blast radius. Give each environment its own state, so a mistake in development cannot reach production. Split large estates by lifecycle: networking changes rarely, application services change weekly. Use one module with different variable files per environment so environments stay similar without sharing fate.

Why it matters for a business

Infrastructure changes start to look like code changes. An engineer opens a pull request, the plan runs automatically, and a reviewer sees exactly what will be added or removed before anything happens. That habit removes most of the surprise from cloud work, because the risky change is visible while it is still cheap to stop.

Recovery gets simpler. If an environment is deleted by accident, or you need the same stack in a second region for a new customer, you point Terraform at a new backend and apply the same code. What used to be a week of console archaeology becomes a review of variables. The code also answers the question new engineers always ask: what actually runs here?

For controls and audits, the repository history is the evidence. Each commit shows who changed which resource and who approved it. That maps cleanly onto change management questions in a SOC 2 or customer security review, far more cleanly than screenshots of a console. Access also tightens: people need permission to merge a pull request, not permanent admin rights in the cloud account.

Common mistakes

State on a laptop is the classic failure. One engineer holds the only copy, a colleague applies from a different machine, and the two records diverge until an apply deletes something live. Use a remote backend with locking from day one. If you already have local state, move it into the backend carefully and keep a backup.

Hand edits in the console are the second. Someone fixes an outage by changing a security group at 2 a.m., nobody updates the code, and the next apply reverts the fix. Either bring the change into code or accept that it will be overwritten. Give most people read-only console access and make the pipeline the only path that writes.

One giant state file is the third. When networking, databases and application services share a state, every plan is slow, every apply is tense, and one mistake reaches everything. Split by lifecycle and team. Moving resources between states is mechanical with terraform state mv, but it is easier to design the split early.

Secrets in the wrong place is the fourth. Do not put passwords in variable files or commit a terraform.tfvars with credentials. State stores many attribute values in plain text, so restrict who can read the bucket and pull secrets from a managed store. Pin provider and module versions and commit the lock file; floating versions turn a routine plan into a surprise.

How to get started

Start with one bounded slice, not the whole estate. A good first target is a new non-production environment or a single service: its network, its database, its bucket and its DNS record. Small enough to finish in days, real enough to prove the workflow and show the team a plan output.

Set up the backend and a CI pipeline before you write many resources. Plan on every pull request, apply only from the pipeline, using a role with the narrowest permissions that still work. Then bring existing infrastructure under management one resource at a time. Write the block, run terraform import, confirm the plan reports no changes. If it wants to change something, your code does not match reality yet; fix the code, not the cloud.

Agree on conventions early because they are hard to change later: a folder per environment, a module per component, consistent names and tags, terraform fmt and validate in CI, and a short README in each folder. Tag every resource with owner and environment so cost and incident questions have an answer.

If you want the surrounding pipeline, environments and guardrails built with you, the Cloudverg Delivery platform setup package is a fixed price option at $14,500 over four weeks, starting within 10 business days. It includes infrastructure as code for the core platform, pipelines, least privilege deploy roles and two training sessions. Doing it in house with a couple of engineers is also a fair path if you have the time.

Frequently asked questions

What is the difference between Terraform and CloudFormation?

Both describe infrastructure as code, but Terraform works across many providers while CloudFormation is specific to AWS. Terraform keeps its own state file and uses HCL, while CloudFormation tracks stacks inside AWS. Teams running more than one cloud usually prefer a single tool for all of it.

Can Terraform manage infrastructure that already exists?

Yes. You write a matching resource block and run terraform import, or use import blocks in newer versions. The plan should then show no changes. If it wants to change something, your configuration does not match the live resource yet.

Do we need Terraform for a small team?

It pays off as soon as more than one person touches infrastructure or you need a second environment. A single developer with one tiny server can manage without it. The cost is small: a backend, a repo and a review habit.

Fixed price

Want help with this? Delivery platform setup

$14,500 fixed price

4 weeks · Starts within 10 business days

Four weeks to give your engineers a delivery platform: pipelines, environments, secrets, monitoring and rollback they can trust.

What is included

Related guides

More devops and platforms guides   Engineering systems

Smallest way to start

Get a senior architect on your problem this week

Ninety minutes on the cloud, AI or security question that is blocking you, a pre-read of your material and a written summary within two business days.

$450 one-time