Terraform and IaC: Managing Infrastructure as Code from Development to Production

Introduction

Imagine being able to deploy an entire data center—servers, databases, networks, load balancers—with a single command in the terminal. Without manually clicking around in AWS, GCP, or Azure consoles. Without the risk of forgetting to configure a Security Group or missing an important tag. This is not science fiction, but a reality provided by Infrastructure as Code (IaC) with Terraform.

Terraform by HashiCorp has become the de facto standard for managing cloud infrastructure. It allows you to describe the desired state of resources in declarative configuration files, and then automatically bring the real infrastructure to that state. In this article, we will break down how Terraform works, which providers it supports, why a state file is needed, and how to use modules to build production-ready systems.

What is Terraform and Why is it the Leader in IaC?

Terraform is an open-source tool that implements the "infrastructure as code" principle. Unlike Ansible or Puppet, which often focus on managing the configuration of already running servers, Terraform deals specifically with provisioning (creating, modifying, and deleting) resources.

Key advantages of Terraform:
- Declarative syntax — you write what the infrastructure should be, not the sequence of commands to achieve it.
- Support for hundreds of providers — from AWS, Azure, GCP to Kubernetes, GitHub, Datadog, and Cloudflare.
- State management — Terraform stores a map of real resources in the terraform.tfstate file, allowing you to track changes and avoid conflicts.
- Modularity — code can be packaged into reusable modules, speeding up development.

Main Components of Terraform

Providers

A provider is a plugin that handles interaction with a specific cloud provider's API. In the configuration, you specify which provider you will use and in which region.

Example configuration for AWS:

provider "aws" {
  region = "us-east-1"
}

To work with multiple clouds, you can specify several providers in one project—for example, simultaneously creating resources in AWS and Azure, combining them into a unified network architecture.

State File (terraform.tfstate)

The state is the "brain" of Terraform. It contains all information about created resources: IDs, IP addresses, dependencies. Without a state file, Terraform does not know what already exists and will try to create everything from scratch.

Problems with local state:
- Loss of the file leads to loss of control over resources.
- Cannot work in a team—conflicts with simultaneous changes.

Solution — remote backend: AWS S3 + DynamoDB, Azure Storage Account, GCP Cloud Storage, or Terraform Cloud. This allows locking the state during writes and storing version history.

Modules

A module is a set of configurations grouped into one directory. They allow you to abstract complex structures and reuse them.

Example module for creating a VPC:

module "vpc" {
  source = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"
  azs  = ["us-east-1a", "us-east-1b"]
  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
  private_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
}

Modules can be taken from the public Terraform Registry or written for specific company needs.

Workflow: From Development to Production

The process of working with Terraform usually looks like this:

  1. Planning — the terraform plan command shows which resources will be created, modified, or deleted, without actually executing.
  2. Applyingterraform apply executes the changes. In production, it is recommended to apply only after the plan is approved.
  3. Destroyingterraform destroy destroys all resources described in the configuration.

For production, it is mandatory to:
- Use a remote backend with locks.
- Version configurations in Git.
- Apply security policies via Sentinel (in Terraform Cloud) or Open Policy Agent.
- Test changes in isolation

← All posts

Comments