Crisp answer: The terraform block sets global configuration: required
provider sources and version constraints, the backend for state storage, and
the minimum Terraform CLI version. It must not use variables or references.
Full example:
terraform {
# Minimum Terraform version required to run this config
required_version = ">= 1.9"
# Provider sources and version constraints
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.30"
}
helm = {
source = "hashicorp/helm"
version = "~> 2.14"
}
}
# Remote state backend
backend "s3" {
bucket = "my-terraform-state"
key = "prod/eks/terraform.tfstate"
region = "eu-west-2"
use_lockfile = true # S3-native locking, Terraform >= 1.9
encrypt = true
}
}
Why required_version matters:
Different Terraform versions have different syntax, behaviours, and provider compatibility. Pinning required_version prevents a team member with an older CLI from silently producing a different plan.
# If your CLI is older than required:
terraform plan
# Error: Unsupported Terraform Core version
# This configuration does not support Terraform version 1.7.0.
Backend configuration rules:
The backend block cannot use variables, locals, or references. Values must be hardcoded strings. This is because the backend must be initialised before Terraform evaluates any expressions.
# WRONG — not allowed:
backend "s3" {
bucket = var.state_bucket # ← variables not allowed in backend
}
# RIGHT — partial configuration with -backend-config:
backend "s3" {}
# Then:
terraform init -backend-config="bucket=my-state-bucket" \
-backend-config="key=prod/terraform.tfstate" \
-backend-config="region=eu-west-2"
The partial configuration pattern (empty backend block with values passed
via -backend-config) is useful for CI pipelines where the state bucket
name differs per environment.
What to say in the interview:
"The terraform block is the global config: required_version pins the CLI version, required_providers declares where to download providers and what version constraints to apply, and backend configures remote state. The backend block has a constraint that prevents variables — values must be literals. This leads to the partial configuration pattern in CI where you pass backend values via -backend-config flags rather than hardcoding environment-specific bucket names."