Terraform is infrastructure as code: it lets you define servers, databases, DNS records, and certificates in text files that you commit to git, review in pull requests, and apply with a single command. As an application developer, you should know enough Terraform to manage your own infrastructure without depending entirely on a dedicated ops person.
What Problem Terraform Solves
Without infrastructure as code, infrastructure is configured manually through cloud provider dashboards. This creates two problems: the configuration is invisible (nobody knows exactly what settings were chosen without logging into every dashboard) and it is not reproducible (recreating the same infrastructure for a new environment requires remembering every manual step).
Terraform solves both problems. Your infrastructure configuration is in HCL (HashiCorp Configuration Language) files. Those files are committed to git. To recreate your entire infrastructure in a new environment, you run terraform apply. To make a change, you edit a file, review the diff, and apply it.
Core Concepts
Providers: Terraform providers are plugins that know how to create resources in a particular service. There are providers for AWS, Google Cloud, Azure, Vercel, Cloudflare, GitHub, PlanetScale, Stripe, and hundreds more. Each provider is declared in your Terraform configuration and downloaded by terraform init.
terraform {
required_providers {
vercel = {
source = "vercel/vercel"
version = "~> 1.0"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
Resources: resources are the things you create: a Vercel project, a Cloudflare DNS record, an Upstash Redis instance. Each resource has a type (from the provider) and a configuration block.
resource "vercel_project" "web" {
name = "my-app"
framework = "nextjs"
git_repository = {
type = "github"
repo = "myorg/my-app"
}
}
Data sources: data sources read existing resources that Terraform did not create. Useful for referencing a zone ID in Cloudflare without hard-coding it.
data "cloudflare_zone" "main" {
name = "example.com"
}
Variables: parameterize your configuration so the same code works for different environments (staging, production) with different values.
variable "environment" {
type = string
default = "production"
}
Outputs: expose values from your Terraform resources for use in other systems or by humans:
output "deployment_url" {
value = vercel_project.web.url
}