Skip to main content
Cloud DevOps Solutions
Get a quote Talk to an engineer

Infrastructure as code

Terraform Consulting and Engineering for Production Cloud Infrastructure

Terraform is a declarative infrastructure as code tool that provisions cloud resources from version-controlled configuration. We design its state layout, modules, pipelines and access controls so that every change to AWS or Azure is reviewed, planned and applied safely, and drift is detected rather than discovered during an outage.

Key takeaways

  • Terraform is a good default for provisioning cloud infrastructure, especially across more than one provider.
  • State layout and module boundaries matter more than syntax. Most painful Terraform estates were shaped by a single oversized state file.
  • Plans should be produced and reviewed in CI, and applies should run from a pipeline with short-lived credentials.
  • Terraform is the wrong tool for configuring the inside of servers or for teams with a single provider and no appetite for a second language.
  • Licensing and the OpenTofu fork are worth a conscious decision, not an accident.

What teams use Terraform for

Landing zones and networking

Accounts, subscriptions, VPCs and VNets, routing, DNS and baseline guardrails defined once and stamped out per environment.

Managed Kubernetes platforms

EKS or AKS clusters, node pools, IAM or identity bindings and add-on prerequisites, provisioned in a repeatable order.

Data and storage layers

Databases, buckets, queues and encryption keys with lifecycle rules and deletion protection written into the code.

Identity and access

Roles, policies and federated pipeline identities kept under review rather than edited in a console.

Adopting existing ClickOps estates

Importing hand-built resources into code without recreating them, then closing the console for changes.

What Terraform is and why teams adopt it

Terraform describes infrastructure in declarative files, compares that description with what exists, and works out the changes needed to close the gap. The value is not the syntax. It is the workflow: a change is written, reviewed as a pull request, planned against real state and then applied, which leaves a record of who changed what and why.

Teams adopt Terraform for three practical reasons. It covers many providers with one workflow, so a cloud account, a DNS zone and a monitoring SaaS can live in the same review process. It has the largest ecosystem of providers and community modules of any tool in its class. And the plan step makes the blast radius of a change visible before anything happens.

Our Terraform infrastructure as code service covers the full engagement. This page explains how we think about running it in production, and when we would steer you elsewhere.

How we structure Terraform in production

State is the foundation

State records which real objects belong to which resources in your code. We store it remotely, versioned and encrypted, with locking, and we limit write access to the pipeline and a small admin group. The detail of that setup is in our guide to Terraform remote state on S3 and Azure Blob.

Equally important is how many state files you have. One state for everything makes plans slow and means an unrelated mistake can touch production networking. We split by change frequency and ownership: network, identity, data platform, each cluster, each application stack. Stacks share values through outputs or data sources rather than by sharing a file.

Modules with opinions, not wrappers

A module that merely re-exposes every argument of a resource adds indirection and no value. Good modules encode a decision: a private subnet layout, an encrypted bucket with logging and public access blocked, a cluster with your agreed node and identity pattern. We version them, pin consumers to a release and document inputs and outputs. See reusable Terraform modules for AWS and Azure for the approach.

Environments

We prefer small root configurations per environment that call the same modules with different inputs. Workspaces share a backend and a code path, which makes it easy to apply the wrong one, so we use them sparingly. Where directory duplication becomes tedious, a wrapper such as Terragrunt can help, but it is an addition with its own costs, not a default.

Security and access

Terraform has broad permissions by design, so the pipeline identity is a high-value target. We use short-lived federated credentials (OIDC from your CI system) rather than stored access keys, and separate plan roles with read access from apply roles with write access. Pull requests from forks never receive apply credentials.

State can contain secrets in plain text, so treat state storage like a production database. Prefer referencing secrets from a secrets manager at runtime over passing them as variables, and mark sensitive outputs. In CI we run static analysis such as Checkov, Trivy or tfsec, covered in Terraform security scanning with Checkov, plus policy as code for rules specific to your organisation.

Cost and capacity

Terraform itself is a build-time tool, so its cost is mostly people time and the infrastructure it creates. Two habits help. First, tag everything through provider-level default tags so spend can be attributed. Second, add a cost estimate step to pull requests so reviewers see the monthly effect of a change next to the plan. We avoid quoting savings, because they depend entirely on what you are running.

Plan time grows with state size, which is another reason to keep stacks small. Parallelism and provider rate limits can also slow large applies, particularly on accounts with many resources.

Day-2 operations

Drift and reconciliation

Someone will change something in the console during an incident. Scheduled plans against each stack detect that, and we treat a non-empty plan as something to reconcile deliberately. Our notes on drift detection and remediation cover the routine.

Upgrades

Provider and core upgrades are routine work, not events. We pin versions, read changelogs, upgrade in lower environments first and keep a lock file committed. The process is detailed in Terraform provider version upgrades.

A minimal pipeline step

jobs:
  plan:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform fmt -check -recursive
      - run: terraform init -input=false
      - run: terraform validate
      - run: terraform plan -input=false -out=tfplan

The apply job runs only after merge, from the saved plan or a fresh plan that is compared with the reviewed one, under a different role.

Common failure modes

  • One huge state file. Slow plans, wide blast radius and lock contention. Fix by splitting stacks and moving resources with state commands under review.
  • Unpinned versions. A provider release changes behaviour on a Monday morning. Pin and upgrade deliberately.
  • Secrets in code or state. Move to a secrets manager and rotate anything already exposed.
  • Stale locks and half-applied changes. Rehearse recovery before you need it.
  • Hand edits in the console. Remove write access for humans, keep break-glass access audited.
  • Modules that nobody owns. Assign owners, version them and write a changelog.

When Terraform is the wrong choice

Be wary of Terraform if your estate is entirely AWS and nobody on the team wants to operate state storage, since AWS CloudFormation removes that burden. If your platform engineers would rather use loops, conditionals and unit tests in TypeScript or Python, Pulumi may feel more natural. If the job is installing packages and managing files on servers, use Ansible for that layer.

On licensing: Terraform moved to the Business Source License in 2023, and the OpenTofu fork continues under an open source licence. Neither is wrong for everyone. We help you read the terms against your actual use and pick deliberately.

If you are starting from a hand-built estate, our article on moving from ClickOps to Terraform on AWS describes the path, and you can book a consultation to scope it.

Official documentation: developer.hashicorp.com/terraform

How we work with Terraform

  1. 01

    Assess the estate

    We inventory what exists, how it was built, who changes it and where the risk sits, then agree what moves into code first.

  2. 02

    Design state and layout

    We choose stack boundaries, the remote backend, environment strategy and naming, before any resources are written.

  3. 03

    Build modules and stacks

    Reusable modules wrap your opinionated patterns, and thin environment stacks consume them with pinned versions.

  4. 04

    Wire the pipeline

    Pull requests run formatting, validation, policy and security checks, then post a plan. Merges apply from a controlled runner.

  5. 05

    Import and reconcile

    Existing resources are imported until a plan shows no unexpected changes, and console write access is then removed.

  6. 06

    Operate and hand over

    Scheduled drift plans, provider upgrade routines and runbooks are documented so your team owns the result.

Terraform compared with the alternatives

We recommend the tool that fits your team, not the one we know best. Here is when each option makes sense.

OptionChoose it when
TerraformTerraform is a declarative infrastructure as code tool that provisions cloud resources from version-controlled configuration.
AWS CloudFormationChoose it if you are AWS-only, want deployments tracked inside AWS itself, and prefer not to manage state storage or a separate toolchain.
PulumiChoose it if your engineers want loops, functions and tests in a general-purpose language and will maintain that code like application code.
OpenTofuChoose it if you want a community-governed open source fork with a compatible workflow, or your legal team requires an OSI-approved licence.
AnsibleChoose it for configuring operating systems and applications on existing machines, not for provisioning cloud resource graphs.

Tools we use alongside Terraform

OpenTofuTerragruntAtlantisCheckovtfsecTrivyInfracostterraform-docsTFLintGitHub ActionsGitLab CI/CDAWS S3Azure Blob StorageOpen Policy Agent

Frequently asked questions

What is Terraform used for?
Terraform is used to create and change cloud infrastructure from declarative configuration files. You describe networks, clusters, databases and permissions in HCL, run a plan to see the exact changes, and apply them. It works across AWS, Azure, Google Cloud and many SaaS providers through provider plugins.
Is Terraform still free to use?
Terraform's source moved from an open source licence to the Business Source License in 2023, which permits most internal use but restricts offering competing commercial products. Many companies are unaffected. OpenTofu, a fork under the Linux Foundation, remains open source. We review your situation and advise on either.
Terraform or OpenTofu: which should we use?
For most teams the day-to-day workflow is very similar, so the decision is mainly about licensing, governance and ecosystem support. We check provider compatibility and your tooling, then recommend one. Keeping modules free of tool-specific features keeps switching later inexpensive.
How should we structure Terraform for multiple environments?
Use reusable modules with small root stacks per environment and per concern, each with its own state. Avoid a single giant state and avoid copy-pasting environments. Variables and pinned module versions carry the differences, and promotion happens through pull requests.
How do you stop Terraform from destroying production?
Layered controls: reviewed plans before any apply, deletion protection and lifecycle prevent_destroy on critical resources, narrow pipeline permissions, and policy checks that block risky changes. State is versioned so a bad write can be rolled back.
Can you adopt our existing console-built infrastructure?
Yes. We import resources into code and iterate until a plan reports no changes, so nothing is recreated. It is slower than greenfield work but it is the safe route, and it usually surfaces unmanaged risk along the way.

Talk to an engineer about Terraform

Book a free 30-minute call. We review your current setup and tell you honestly whether and how we can help.

Written by Saddique Khan, DevOps / SRE / Cloud Consultant Engineer. Last updated 2026-10-09.