Terraform Resources Building Blocks of Infrastructure
Resources are the most important concept in Terraform. Every virtual machine, every database, every network subnet — all of these are resources in Terraform. This topic explains how to write resource blocks, understand their arguments, reference their attributes, and manage their behavior.
What Is a Resource
A resource represents a single infrastructure object. It could be a physical server, a virtual machine, a DNS record, a storage bucket, or any other piece of infrastructure that a cloud provider can create.
Analogy: Lego Bricks
Think of your entire infrastructure as a Lego model. Each individual Lego brick is a resource. A web server is one brick. The database it connects to is another brick. The network they share is a third brick. Terraform snaps those bricks together exactly as you describe in your code.
The Resource Block Syntax
resource "RESOURCE_TYPE" "LOCAL_NAME" {
argument1 = value1
argument2 = value2
}
- RESOURCE_TYPE: Determined by the provider. For AWS it might be
aws_instance,aws_s3_bucket, oraws_vpc. - LOCAL_NAME: A name you choose. It exists only inside Terraform and is never sent to the cloud provider. Use descriptive names like
web_server,app_database, ormain_network.
A Real Example: AWS EC2 Instance
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "My Web Server"
Environment = "Production"
}
}
Diagram: Resource Block Anatomy
resource "aws_instance" "web_server" {
^ ^ ^
Block Resource Your
Type Type Local Name
(always (from the (you choose)
"resource") provider docs)
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
^ ^
Required Required
Argument Argument
tags = { Name = "My Web Server" }
^
Optional Argument (key-value map)
}
Required vs Optional Arguments
Each resource type has its own set of arguments. Some arguments are required — Terraform will refuse to create the resource without them. Other arguments are optional — if you omit them, the provider uses its default value.
You find the full list of arguments for any resource in the provider documentation on registry.terraform.io. For example, searching for aws_instance shows every argument, whether it is required, and what it does.
Referencing Resource Attributes
After Terraform creates a resource, it stores the resource's attributes in the state file. You reference those attributes in other resources using dot notation.
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
}
resource "aws_eip" "web_ip" {
instance = aws_instance.web_server.id
^ ^ ^
resource type name attribute
}
The format is: RESOURCE_TYPE.LOCAL_NAME.ATTRIBUTE
This reference creates an implicit dependency — Terraform automatically creates the EC2 instance before trying to attach the Elastic IP, because the EIP needs the instance ID.
Common Resource Types Across Providers
| Provider | Resource Type | What It Creates |
|---|---|---|
| AWS | aws_instance | Virtual machine (EC2) |
| AWS | aws_s3_bucket | Object storage bucket |
| AWS | aws_vpc | Virtual Private Cloud (network) |
| Azure | azurerm_virtual_machine | Virtual machine |
| Azure | azurerm_resource_group | Logical container for Azure resources |
| GCP | google_compute_instance | Virtual machine |
| GitHub | github_repository | A new GitHub repository |
Nested Blocks Inside Resources
Some resources contain nested configuration blocks. These are not separate resources — they are sub-configurations that belong to the parent resource.
resource "aws_instance" "app_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.small"
root_block_device {
volume_size = 20
volume_type = "gp3"
encrypted = true
}
network_interface {
network_interface_id = aws_network_interface.main.id
device_index = 0
}
}
The root_block_device and network_interface blocks configure aspects of the EC2 instance itself. They are not standalone resources — they live inside the aws_instance resource block.
Key Points
- A resource block defines one infrastructure object — a server, bucket, database, or network element.
- The resource type comes from the provider; the local name is yours to choose.
- Reference another resource's attribute with the pattern
resource_type.local_name.attribute. - Attribute references create implicit dependencies that control the order Terraform creates resources.
- Read provider documentation on the Terraform Registry to find all available arguments for any resource type.
