Back

Infrastructure as Code: A Terraform Starting Point

A grounded intro to Terraform — remote state, modules, plan-before-apply discipline, and the early mistakes that turn IaC into a liability.

Infrastructure as Code: A Terraform Starting Point
Written by
BSH Technologies
Published on2026-06-06

Terraform turns your infrastructure into reviewable code

Infrastructure as Code with Terraform means your cloud resources are described in version-controlled files instead of clicked together by hand in a console. The payoff is real: changes go through pull requests, environments become reproducible, and you can tell exactly what is deployed by reading the repository. The risk is that a tool this powerful can also delete a database with a single careless apply. Starting with the right habits is what separates IaC that helps from IaC that hurts, and almost all of those habits are about respecting two things — the state file and the plan.

State is the heart of Terraform — put it somewhere safe

Terraform tracks what it has created in a state file. That file is the single source of truth mapping your code to real resources, and it is the first thing to get right.

  • Never keep state on a laptop or commit it to git — it contains resource metadata and sometimes secrets.
  • Use a remote backend such as an S3 bucket or a GCS bucket so the whole team and your CI pipeline share one authoritative copy.
  • Enable state locking so two applies cannot run at once and corrupt the file.
  • Turn on versioning of the state bucket so you can recover from a bad write.

A corrupted or lost state file is one of the few genuinely painful Terraform failures, because Terraform no longer knows which real resources it owns and may try to recreate things that already exist. Remote state with locking and versioning prevents almost all of it, and it is the single highest-value thing to set up before your second engineer ever runs a command.

Plan before you apply, every single time

The plan command shows exactly what Terraform intends to do — what it will create, change, and crucially what it will destroy — before anything happens. Read it. The most expensive Terraform incidents happen when someone runs apply without reading the plan and a change they thought was additive quietly forced a resource to be replaced.

  • Run plan in your pipeline and require a human to review it on anything touching production.
  • Watch for the word destroy and for replacements, which appear when a change cannot be made in place.
  • Treat a plan with unexpected deletions as a stop signal, not a prompt to type yes.

Some attribute changes can be applied in place, while others force the resource to be torn down and rebuilt — and the difference is not always obvious from the size of the edit. A one-line change to a field that cannot be updated live will replace the whole resource, which for a database means downtime and possibly data loss. The plan tells you this plainly if you read it. The discipline of always reading the plan, even when you are sure the change is trivial, is what keeps that surprise from reaching production.

Modules keep you from copy-pasting your way into chaos

Once you have more than one environment, you will be tempted to copy your dev configuration into a staging folder and edit a few values. Resist it. Wrap reusable pieces — a network, a service, a database — in a module and call that module from each environment with different inputs. When you need to change how a service is provisioned, you edit the module once instead of hunting through three near-identical copies that have already drifted apart.

Keep modules small and focused. A module that tries to provision your entire platform is as hard to reason about as the click-ops it replaced. A good module does one job, exposes a handful of clear inputs, and returns a few useful outputs — much like a well-named function. Resist the urge to add a flag to a module for every minor variation; past a point, a configurable mega-module is harder to understand than two simple ones.

Separate environments so a dev mistake cannot reach production

Keep dev, staging, and production in separate state files, ideally with separate credentials. The goal is that running apply against dev has no physical path to touch production. Use workspaces or separate directories per environment, and scope each environment's cloud credentials to only what it owns. This single piece of structure prevents an entire category of accidents — the kind where someone is sure they are pointed at staging and they are not. When the credentials themselves cannot reach production, that mistake becomes harmless instead of catastrophic.

Let Terraform own everything, or own nothing

The messiest Terraform setups are the half-managed ones, where some resources are in code and others were created by hand and edited around. Terraform does not know about resources it did not create, and manual changes to resources it does manage get reverted on the next apply, surprising whoever made them. Pick a clear boundary for what Terraform owns and keep manual changes out of it. When something must change, change the code. If you must adopt an existing hand-built resource, import it into state deliberately rather than letting Terraform and the console quietly fight over it.

How BSH can help

BSH Technologies sets up Infrastructure as Code on GCP and AWS for teams that want reproducible, reviewable environments without the foot-guns. Whether you are adopting Terraform for the first time or untangling a state file that has drifted from reality, we can establish remote state, structure your modules and environments, and wire plan-and-apply into a pipeline your team can trust. Reach out and we will help you start on solid ground.

From the blog

View all posts
Designing Multi-Tenant SaaS That Scales
Software Dev

Designing Multi-Tenant SaaS That Scales

Choosing an isolation model, keeping tenant data separate, and dodging the noisy-neighbour and migration traps that bite SaaS later.

BSH Technologies
BSH Technologies · 2026-06-14
Hitting Green Core Web Vitals in Next.js
Software Dev

Hitting Green Core Web Vitals in Next.js

A practical guide to LCP, INP and CLS in Next.js — image handling, font loading, the App Router boundary, and costly third-party scripts.

BSH Technologies
BSH Technologies · 2026-06-10