Ideas Engineered for Tomorrow
We Engineer Services & Solutions for Your Business Needs
Home About
Products
Services
Hire
Industries
Consulting
Partners
Articles Careers Contact
Cloud & DevOps

Infrastructure as Code with Terraform: Complete Guide

We manage 200+ cloud resources across 8 client environments with Terraform. Zero ClickOps, full reproducibility, complete audit trails. Here's how we set it up — and the mistakes that cost us weeks.

March 12, 2026 15 min read
In this article

If you're still creating cloud resources by clicking through a web console, you're building on quicksand. Console-created infrastructure is undocumented, unreproducible, and un-reviewable. When something breaks at 2 AM, nobody knows what the expected state should be.

Terraform solves this by treating infrastructure as code — version-controlled, peer-reviewed, and automatically applied. At Pillai Infotech, every piece of infrastructure we manage (for our own operations and for clients) is defined in Terraform. No exceptions.

Why Terraform Won the IaC Market

  • Multi-cloud: One language (HCL) for AWS, Azure, GCP, and hundreds of other providers. No vendor lock-in.
  • Declarative: You describe the desired state, Terraform figures out how to get there. No imperative scripting.
  • Plan before apply: terraform plan shows exactly what will change before anything happens. No surprises.
  • State management: Terraform knows what exists and what needs to change. It doesn't blindly recreate everything.
  • Massive ecosystem: 3,000+ providers covering everything from cloud infrastructure to DNS, monitoring, databases, and SaaS tools.

Terraform vs Alternatives

Tool Approach Best For
Terraform Declarative HCL, multi-cloud Most teams, multi-cloud, largest ecosystem
Pulumi Real programming languages (TypeScript, Python) Teams who prefer code over config, complex logic
CloudFormation AWS-native YAML/JSON AWS-only shops, deep AWS integration
OpenTofu Open-source Terraform fork Teams concerned about HashiCorp licensing

Core Concepts You Need to Understand

Resources

The fundamental building blocks. Each resource represents a single piece of infrastructure — an EC2 instance, an S3 bucket, a database, a DNS record.

Providers

Plugins that connect Terraform to cloud platforms. provider "aws", provider "azurerm", etc. You can use multiple providers in one configuration.

State

A file (local or remote) that tracks what Terraform manages. It maps your config to real-world resources. This is the most important concept to understand. State is how Terraform knows what exists, what to create, what to update, and what to destroy.

Plan and Apply

terraform plan shows you what will change. terraform apply makes those changes. Always plan before applying. In CI/CD, plan on PR, apply on merge.

Module Design: Reusable Infrastructure Components

Modules are Terraform's abstraction mechanism — reusable packages of infrastructure that accept inputs and produce outputs. Good module design is the difference between maintainable Terraform and copy-paste chaos.

Our Module Rules

  1. One module per logical component: A "web-app" module that creates load balancer + auto-scaling group + security group + CloudWatch alarms. Not separate modules for each.
  2. Inputs for everything that varies: Environment name, instance size, region, tags. Hard-code nothing that differs between staging and production.
  3. Sensible defaults: Most inputs should have defaults that work for the common case. Teams shouldn't need to specify 30 variables to create a database.
  4. Version your modules: Use semantic versioning (Git tags) for shared modules. A module change shouldn't break every team simultaneously.

State Management: Don't Learn This the Hard Way

State management is where most Terraform disasters happen. Here's how to get it right:

  • Remote state: Store state in S3 + DynamoDB (AWS), Azure Blob + Table Storage, or GCS + Cloud Storage. Never in local files. Never in Git.
  • State locking: DynamoDB table for AWS, built-in for Azure/GCP. Prevents two people from modifying state simultaneously.
  • State encryption: Enable server-side encryption on your state bucket. State files contain sensitive information (resource IDs, sometimes passwords).
  • State isolation: Separate state files per environment (staging, production) and per team/component. A single state file for everything is fragile — one bad apply takes down everything.
Lesson learned: We once had a junior engineer run terraform destroy in the wrong directory, targeting production state instead of a test environment. State isolation would have prevented this. We now use separate AWS accounts per environment and separate state backends. The 30 minutes to set up isolation saves potentially catastrophic mistakes.

Workspaces and Environment Management

Terraform workspaces allow you to manage multiple environments from the same configuration. However, we prefer a different approach:

Our Approach: Separate Directories, Shared Modules

terraform/
├── modules/ # Shared reusable modules
│ ├── web-app/
│ ├── database/
│ └── networking/
├── environments/
│ ├── staging/ # Staging-specific config + state
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ └── production/ # Production-specific config + state
│ ├── main.tf
│ ├── variables.tf
│ └── terraform.tfvars
└── global/ # Shared resources (IAM, DNS)

Each environment has its own state backend, its own variables, and its own Terraform configuration that references shared modules. This is more verbose than workspaces but much safer — you literally cannot accidentally apply production changes to staging or vice versa.

Terraform in CI/CD Pipelines

  1. On PR: Run terraform plan and post the output as a PR comment. Reviewers see exactly what infrastructure changes the PR introduces.
  2. On merge to main: Run terraform apply -auto-approve for staging. Require manual approval for production.
  3. Drift detection: Schedule a daily terraform plan in production. If someone made manual changes (ClickOps), the plan will show drift.

Tools that make this easier: Atlantis (PR-based Terraform automation), Terraform Cloud, Spacelift. We use Atlantis for most clients — it's open source and runs in your own infrastructure.

The 5 Terraform Mistakes That Cost Us the Most Time

  1. Not using remote state from day one. Migrating from local to remote state is doable but nerve-wracking. Start with remote state, even for experiments.
  2. Monolithic state files. One state file for everything means one terraform apply can touch everything. Split by environment and component.
  3. Not pinning provider versions. A provider update changed API behavior and broke our plan. Always pin: required_providers { aws = { version = "~> 5.0" } }
  4. Ignoring import. When you have existing infrastructure, use terraform import to bring it under management. Don't recreate resources that already exist.
  5. Testing in production. Terraform has no "undo." Test in a disposable environment first. We maintain a "sandbox" environment specifically for Terraform experiments.

Need help setting up Terraform for your infrastructure? Our DevOps team implements IaC from scratch or takes over existing configurations. Let's talk.

Frequently Asked Questions

Should I use Terraform or Pulumi?

Terraform if your team is comfortable with HCL (most are) and you want the largest ecosystem. Pulumi if your team strongly prefers writing infrastructure in TypeScript/Python and you need complex logic (loops, conditionals) that HCL handles awkwardly. Both are production-ready.

Is OpenTofu a viable alternative?

Yes. OpenTofu is a community fork of Terraform that's fully compatible with existing Terraform configurations. It's governed by the Linux Foundation and backed by major companies. If HashiCorp's BSL license concerns you, OpenTofu is a safe alternative.

How do I manage secrets in Terraform?

Never store secrets in Terraform state or variables files. Use a secrets manager (AWS Secrets Manager, HashiCorp Vault, Azure Key Vault) and reference secrets by ARN/path. For state encryption, enable server-side encryption on your backend. For sensitive outputs, mark them with sensitive = true.

How long does it take to learn Terraform?

Basic proficiency (creating resources, using modules): 1-2 weeks. Production-grade usage (state management, CI/CD, module design): 1-2 months. Expert level (custom providers, complex state manipulation): 6+ months. The learning curve is manageable for experienced engineers.

Can Terraform manage Kubernetes resources?

Yes, via the Kubernetes provider. However, we recommend using Helm or ArgoCD for Kubernetes application deployments and Terraform for the underlying infrastructure (the Kubernetes cluster itself, networking, IAM). Mixing application and infrastructure management in one tool creates tight coupling.

Need Help with Infrastructure as Code?

We implement Terraform from scratch, migrate existing infrastructure, and train your team on IaC best practices.

Get a Free IaC Assessment Our DevOps Services