100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
HCL

Resources and Resource Blocks

The resource block is Terraform's fundamental unit of infrastructure declaration, describing a single managed object like a virtual machine, network, or storage bucket.

Terraform Core WorkflowBeginner8 min readJul 9, 2026
Analogies

Resources and Resource Blocks

A resource block is the fundamental building block of any Terraform configuration. Each resource block declares a single infrastructure object — an EC2 instance, an S3 bucket, an Azure resource group, a Kubernetes deployment — that Terraform should create and manage on your behalf. The general syntax is resource "<PROVIDER_TYPE>" "<LOCAL_NAME>" { ... }, where the provider type identifies which kind of object it is (and implicitly which provider handles it) and the local name is an identifier used only within the configuration to refer to that resource elsewhere.

🏏

Cricket analogy: A resource block is like declaring a single player contract on the team sheet — 'resource player web' — specifying exactly which role and which identifier Terraform (the team management) uses to track that player throughout the season.

Anatomy of a Resource Block

Inside the block's body, arguments configure the resource's attributes — for an aws_instance, that might include ami, instance_type, and tags. Different resource types have entirely different sets of valid arguments, documented on the Terraform Registry page for that resource. Some arguments are required (Terraform will error if omitted), others are optional with sensible defaults, and some are computed entirely by the provider after creation (like an assigned IP address), accessible only as an output attribute, never as an input argument.

🏏

Cricket analogy: Like a player's contract listing required terms (jersey number, team) as required arguments, optional terms (preferred batting position) with defaults, and computed stats (final season average) that only appear after the season, never set upfront.

Referencing Resource Attributes

Once declared, a resource's attributes can be referenced elsewhere in the configuration using the syntax <TYPE>.<LOCAL_NAME>.<ATTRIBUTE> — for instance, aws_instance.web.id or aws_subnet.public.cidr_block. This is how Terraform builds its dependency graph: when one resource block references another resource's attribute, Terraform automatically infers that the referenced resource must be created first, and orders operations accordingly without the engineer needing to specify ordering manually.

🏏

Cricket analogy: Like referencing a bowler's current economy rate as 'bowler.jadeja.economy' when setting the next over's field placement — Terraform infers the fielding captain must set jadeja's stats before referencing them, ordering the plan automatically.

The Resource Address

Every resource in a configuration has a unique 'resource address' — combining its type and local name (and, for resources using count or for_each, an index or key) — such as aws_instance.web or aws_instance.web[0]. This address is what Terraform uses internally to track the resource in state, and what you use with CLI commands like terraform state show aws_instance.web or terraform import aws_instance.web i-0abc123.

🏏

Cricket analogy: Like a player's unique registration number combining team and jersey number (and match number for substitutes) — 'team.player[2]' — used by the scoring system to look up or reassign that exact player, just as terraform state show works.

A resource's local name (the second string in the block header) is purely a configuration-time label -- changing it doesn't change anything about the real infrastructure directly, but it DOES change the resource's address in state. Renaming a local name without using a moved block or terraform state mv will cause Terraform to plan a destroy-and-recreate, since as far as state is concerned, the old address's resource no longer exists in configuration and a brand new one has appeared.

Deleting a resource block from your configuration and running apply will DESTROY that real resource, not just stop managing it. If you want Terraform to forget about a resource without destroying it, use terraform state rm (or, more safely, a removed block in newer Terraform versions) instead of simply deleting the block and applying.

hcl
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id        # implicit dependency
  cidr_block        = "10.0.1.0/24"
  availability_zone = "us-east-1a"

  tags = {
    Name = "public-subnet"
  }
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public.id       # implicit dependency

  tags = {
    Name = "web-server"
  }
}

# Referencing computed attributes elsewhere, e.g. in an output:
output "web_instance_id" {
  value = aws_instance.web.id
}
  • A resource block declares one infrastructure object using resource "<TYPE>" "<LOCAL_NAME>" { ... }.
  • Arguments inside the block configure the resource; available arguments vary by resource type.
  • Referencing resource.attribute elsewhere creates an implicit dependency Terraform orders automatically.
  • Each resource has a unique address (type.name, or type.name[index] for count/for_each) tracked in state.
  • Renaming a resource's local name changes its address and will trigger a destroy/recreate unless handled with moved blocks.
  • Deleting a resource block and applying destroys the real resource -- use state rm or removed blocks to stop managing without destroying.

Practice what you learned

Was this page helpful?

Topics covered

#HCL#TerraformInfrastructureAsCodeStudyNotes#DevOps#ResourcesAndResourceBlocks#Resources#Resource#Blocks#Anatomy#StudyNotes#SkillVeris