Skip to main content

Providers, resources, modules: the Terraform trinity

Summary: three words come up constantly in any Terraform code, and they must be clearly distinguished. The provider is the bridge between Terraform and a platform (AWS, GCP, Azure, GitHub, Datadog, etc.). The resource is a concrete infrastructure brick created by Terraform (VM, database, DNS). The module is a packaged, reusable set of resources. This lesson dissects the trinity, adds a fourth key concept — the data source — and shows where to find them in the Terraform Registry.


1. Overview of the Terraform architecture

In one sentence: your code declares a provider, which gives you access to resources, which you can organize into modules shareable via the Registry.


2. Providers — the bridges to each platform

A provider is a plugin downloaded by Terraform that knows how to talk to the API of a given platform.

2.1 · What a provider brings

2.2 · How many providers exist?

More than 3500 providers are available in the Terraform Registry in 2026. They cover:

What makes Terraform so powerful: you can provision your AWS server, your Cloudflare DNS, your GitHub repo and your Datadog alert in a single HCL file. It is this multi-platform unification that built Terraform's dominance.

2.3 · The types of providers

Best practice: always favour official or partner providers. Community providers can be excellent, but their maintenance can stop overnight.


3. Resources — the concrete bricks

A Terraform resource represents an entity that can be created on a platform: a virtual machine, an S3 bucket, a DNS record, an IAM user, a GitHub repo, a Datadog alert.

3.1 · Anatomy of a resource

Syntax reminder:

resource "RESOURCE_TYPE" "LOGICAL_NAME" {
attribute_1 = value
attribute_2 = value
}

Concrete examples:

Resource blockWhat it creates
resource "aws_instance" "web"An EC2 VM on AWS
resource "google_compute_instance" "web"A Compute Engine VM on GCP
resource "azurerm_virtual_machine" "web"A VM on Azure
resource "kubernetes_deployment" "app"A Kubernetes Deployment
resource "github_repository" "docs"A GitHub repo
resource "cloudflare_record" "www"A Cloudflare DNS record
resource "datadog_monitor" "cpu"A Datadog alert

3.2 · Composed resources and dependencies

Resources compose in cascade to build complete architectures.

Remarkably: Terraform detects these dependencies automatically from the references (aws_vpc.main.id). You never have to specify the order — it infers it.

3.3 · Meta-arguments — fine-grained behaviour control

Some attributes are special — they do not represent a property of the cloud resource, but an instruction for Terraform itself.

These meta-arguments are Terraform's engine room — they let you tune the behaviour very finely.


4. Data sources — reading without creating

There is a cousin of resources you must know: data sources.

Fundamental difference:

  • A resourcecreates a new entity.
  • A datareads an existing entity.

Example: you want to use the most recent Ubuntu AMI in your region, without hard-coding its identifier (which changes with every update).

data "aws_ami" "ubuntu_latest" {
most_recent = true
owners = ["099720109477"] # Canonical

filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-*"]
}
}

resource "aws_instance" "web" {
# We use the ID found by the data source
ami = data.aws_ami.ubuntu_latest.id
instance_type = "t3.micro"
}

What this enables:

Data sources = read-only. No change is made to the infrastructure. It is your tool to connect Terraform to what already exists.


5. Modules — the unit of reuse

A Terraform module is a structured set of .tf files packaged for reuse.

5.1 · Anatomy of a module

A module can be local (in a subfolder of your project) or remote (downloaded from the Terraform Registry, GitHub, GitLab, S3…).

5.2 · Using a remote module — the magic example

In 5 lines of HCL, you can create a complete AWS VPC thanks to a renowned community module:

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

name = "my-production-vpc"
cidr = "10.0.0.0/16"

azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

enable_nat_gateway = true
single_nat_gateway = false
}

What it actually creates: a VPC, 6 subnets, 3 NAT Gateways, a route table, an IGW, several default security groups… about 25 AWS resources. And you only wrote 10 lines.

That is all the magic of modules: the community has built and tested the standard infrastructure patterns, and you consume them like Lego bricks.

5.3 · The Terraform Registry — the global catalogue

The Terraform Registry is the marketplace where everyone publishes their modules and providers.

The star modules to know:

ModuleWhat it does
terraform-aws-modules/vpc/awsComplete AWS VPC with subnets, NAT, routing
terraform-aws-modules/eks/awsTurnkey EKS Kubernetes cluster
terraform-aws-modules/rds/awsRDS database with replication
hashicorp/consul/awsConsul cluster in HA
cloudposse/vpc/awsAWS VPC, Cloud Posse variant

Always check:

  • The number of downloads (adoption indicator).
  • The date of the last update (ideally less than 6 months).
  • The licence (MPL, Apache 2, MIT are reliable).
  • The GitHub repo — active issues, multiple contributors.

6. Complete cycle — putting it all together

Here is how these four building blocks (provider, resource, data, module) fit together in a real project.

A mature Terraform project uses these four building blocks together, and 80% of its code consists of assembling existing modules rather than writing raw resources.


7. The classic beginner mistakes

A beginner typically makes the following mistakes.

The Premium Terraform Course puts a lot of emphasis on best practices of structure and avoids these pitfalls.


Remember in 30 seconds

  • Provider = plugin that talks to an API (AWS, GCP, GitHub, Datadog). More than 3500 available.
  • Resource = an entity that Terraform can create (VM, database, DNS). The heart of all Terraform code.
  • Data source = read-only access to an existing entity — used to query without modifying.
  • Module = reusable package of resources, with variables and outputs. The secret of scalability.
  • Terraform Registry = global catalogue with 15,000+ public modules.
  • Best practice: never reinvent a module that already exists in the Registry.

Next: The state file: the file that makes Terraform smart →