How Terraform uses providers
Terraform Core, providers, and the API
You write resource "aws_instance" "web" { ... }, run terraform apply, and a virtual machine appears in your cloud account. Nothing in the terraform binary itself knows what an EC2 instance is or how to call Amazon's API; that knowledge lives in a provider. This section pins down the three-part relationship a provider sits in, so that by the end you can say which component holds the API logic, which one builds the plan, and how the two talk to each other.
A provider is a plugin that Terraform uses to interact with one target platform. Terraform relies on plugins called providers to interact with cloud platforms, SaaS providers, and other APIs[1], and it is the provider, not Terraform itself, that carries the platform-specific logic. The piece you invoke on the command line is Terraform Core, the terraform binary: it parses your configuration, builds the dependency graph and the plan, and manages state, but it holds no API logic for any particular platform. Because Terraform creates and manages resources on cloud platforms and other services through their application programming interfaces (APIs)[2], and Core has none of that API code, a provider is required for Core to reach any real infrastructure.
Terraform Core and a provider are separate programs. Terraform Core uses remote procedure calls (RPC) to communicate with Terraform Plugins[3], and each plugin is executed as a separate process that communicates with the main Terraform binary over that RPC interface. This clean split is what lets providers be built and shipped on their own: one side, Core, is the same for everyone, and the other side, the provider, is swapped in per platform. The figure shows the path a request travels, from Terraform Core, over RPC, to the provider plugin, which then calls the platform's API.
What a provider adds: resource types and data sources
A provider's job is to add resource types and turn them into API calls. Each provider adds a set of resource types and/or data sources that Terraform can manage[1], and every resource type is implemented by a provider; without providers, Terraform can't manage any kind of infrastructure[1]. Terraform Core therefore ships with no built-in resource types of its own: an aws_instance, a google_storage_bucket, and a kubernetes_deployment all exist only because some provider defines them.
A provider exposes two kinds of things. A resource type describes an object whose lifecycle Terraform manages, and a data source is a read-only lookup: data sources fetch data from the provider, but do not create or modify resources[4], they only read existing information for the rest of your configuration to use. Both come from the provider, so the difference is ownership, not origin. Reach for a data source when you need to read something you do not manage, such as an existing image ID or a network another team owns.
When Terraform applies a change, the provider is what actually contacts the platform. It translates each declared resource into the underlying create, read, update, and delete (CRUD) calls of that platform's API, so a single resource block can become several API requests over its life: a create on first apply, reads to detect drift, updates when arguments change, and a delete on destroy. Core never calls the platform API directly; it hands the intent to the provider, and the provider issues the CRUD API calls. The figure traces one resource from your configuration, through its provider, to the create, read, update, and delete requests the platform API executes.
Selecting and installing providers
Terraform figures out which provider to use from your resource types, then installs the matching plugins. If a resource doesn't specify which provider configuration to use, Terraform interprets the first word of the resource type as a local provider name[5]: aws_instance selects the aws provider because aws is the type prefix, not because of the resource's second label (web, db, or whatever you named it). It is the type prefix that picks the provider; the name you give the resource is only an address label and never chooses a provider. Nearly every provider has a preferred local name, which it uses as a prefix for all of its resource types[5], which is why the prefix is a reliable signal. A resource can override the default by setting the provider meta-argument explicitly, but absent that, the prefix decides.
To install a provider, Terraform needs more than a local name; it needs a source address and any version constraints. These live in a required_providers block[5] nested in the top-level terraform block, where each entry maps a local name to a source address such as hashicorp/aws plus an optional version constraint. The Terraform Registry is the main directory of publicly available Terraform providers[1] and is the default location Terraform downloads them from.
terraform init ties this together. During init, Terraform searches the configuration for both direct and indirect references to providers and attempts to install the plugins for those providers[6]. By default it downloads plugins into a subdirectory of the working directory[7], the .terraform directory, so each working directory is self-contained, and after successful installation, Terraform writes information about the selected providers to the dependency lock file[6] (.terraform.lock.hcl) so later runs reuse the same versions. The figure follows that pipeline, from the configuration's provider requirements, through terraform init, which finds the referenced providers, to a download from the Registry and an install into .terraform with the lock file recording the versions.
Exam-pattern recognition
TA-004 items on this objective test whether you can describe the division of labor between Terraform and its providers. No provider-specific resource knowledge is required; the questions turn on the relationship, not on any one cloud's arguments.
A frequent stem asks whether Terraform has built-in support for a cloud service, or what a provider actually is. The right answer is that a provider is a plugin and that Terraform Core has no built-in resource types, so a provider is required for every platform; reject any option claiming Terraform manages a cloud natively without one. A close variant asks whether Terraform Core calls the platform API directly. It does not: Core hands intent to the provider over RPC, and the provider makes the create, read, update, and delete calls. Choose the option that keeps the API logic in the provider.
Another stem asks why a provider's version differs from the Terraform CLI version, or why you pin the two separately. The answer is that providers are distributed separately from Terraform itself, and each provider has its own release cadence and version numbers[1]; a provider version does not track the Terraform version. A related item asks which provider manages aws_instance. Answer from the type prefix, aws, and do not be tempted by the resource's name label, which never selects a provider.
A fourth pattern asks what terraform init does for providers, or where the plugins go. Safe answers: init reads the configuration, downloads the required providers (by default from the Terraform Registry), installs them under the .terraform directory, and records the chosen versions in the dependency lock file. Distractors place the plugins in a global-only location or claim the resource block alone, without init, installs them; both miss the init step. Finally, if an item contrasts a resource with a data source, remember both come from a provider, but only a resource type has a managed CRUD lifecycle, while a data source is read-only.
The division of labor: Core, provider, and API
| Aspect | Terraform Core | Provider plugin | Target platform API |
|---|---|---|---|
| Infrastructure knowledge | None; no platform-specific logic | Implements one platform's resource types and data sources | The real system being managed |
| Main job | Builds the plan and dependency graph | Translates resources into CRUD API calls | Executes the create, read, update, delete requests |
| How it is reached | The `terraform` CLI you run | Launched as a separate process, RPC to Core | Called by the provider over the network |
| Distribution | Shipped in the Terraform release | Released separately, its own version numbers | Owned by the platform vendor |
| Installed by | Installing Terraform | `terraform init`, into `.terraform` | Not installed; it is the remote endpoint |
Sharp facts the exam loves — give these one last read before exam day.
Cheat sheet
Sharp facts the exam loves — scan these before test day.
- Providers are plugins Terraform relies on
Terraform relies on plugins called providers to interact with cloud platforms, SaaS providers, and other APIs; Terraform Core itself contains no infrastructure-specific logic and delegates all API interaction to providers.
Trap Thinking Terraform has built-in support for cloud services without a provider.
11 questions test this
- A stakeholder assumes that because Terraform 'creates and manages resources on cloud platforms,' it must ship with native, built-in support for each cloud's services out of the box. Which statement mo
- A team needs Terraform to manage a niche SaaS platform that HashiCorp does not maintain an official provider for. A colleague argues this is impossible, claiming that only HashiCorp can add support fo
- A new team member asks why HashiCorp describes Terraform as being 'logically split into two main parts.' At the associate level, which description best captures the relationship between Terraform Core
- During a design review, a colleague claims that Terraform can manage any resource type on its own as long as the HCL syntax is valid, without needing a provider for that platform. Why is this claim in
- A practitioner writing their first configuration wonders how Terraform knows which arguments an aws_instance resource accepts, given that the Terraform CLI itself ships with no AWS-specific code. Whic
- A new engineer is surprised that one tool can manage thousands of different platforms - AWS, Kubernetes, GitHub, Datadog, and many more - from a single CLI. Which statement best explains the design ch
- While debugging a failed run, an engineer asks which part of Terraform actually authenticates to the target platform and issues the create, read, update, and delete API calls for each resource. At the
- A practitioner browsing the Terraform Registry sees provider entries for AWS, Azure, Kubernetes, and GitHub. At the associate level, what is one of these provider entries, in terms of how Terraform ac
- During onboarding, a teammate asks what a Terraform provider actually contributes to a configuration once terraform init has installed it. At the associate level, which description most accurately cap
- A configuration contains only input variables, locals, and outputs, and declares no providers at all. A practitioner claims Terraform can still create cloud infrastructure from it because Terraform is
- Your team is standing up a new Terraform project that will manage resources on a cloud platform your organization has never automated with Terraform before. A colleague asks how Terraform is able to t
- Providers are versioned separately from Terraform
Providers are distributed and released separately from the Terraform CLI, each with its own version numbers and release cadence, which is why provider versions are constrained independently of the Terraform version.
Trap Assuming a provider's version tracks the Terraform CLI version.
8 questions test this
- A practitioner is editing the required_providers block for the AWS provider and wants to require any released version at or above 3.1, written with Terraform's version-constraint syntax. Which version
- A practitioner notices their configuration uses AWS provider version 5.x while the Terraform CLI they run reports version 1.12. A colleague worries this is a version mismatch and says the AWS provider
- While reviewing the AWS provider's page on the Terraform Registry, an engineer notices it has published far more releases over the past year than the Terraform CLI has. A teammate assumes each provide
- During a discussion about pinning dependencies, an engineer explains why Terraform lets you constrain provider versions in the configuration independently of the Terraform CLI version itself. Which re
- A practitioner upgrades the Terraform CLI on their workstation from v1.11 to v1.12 and then wonders whether the AWS provider that their configuration already uses will automatically move to a matching
- A practitioner adds required_version = ">= 1.5" to the terraform block, believing this also guarantees a recent AWS provider will be selected. During review, a teammate asks what required_version actu
- A team is blocked by a confirmed bug in the Azure provider and asks when the fix will reach them. One engineer states they must wait for the next Terraform CLI release before the fix can be delivered.
- A single Terraform configuration declares two providers: the AWS provider constrained to a 5.x release and the random provider constrained to a 3.x release. A reviewer objects that every provider in o
- Core talks to providers over a plugin protocol
Terraform Core communicates with each provider plugin over an RPC-based plugin protocol, launching the provider as a separate process during operations.
- Each provider adds resource types and data sources
Each provider defines a set of resource types and/or data sources that Terraform can manage; a provider is required for every resource type, so Terraform cannot manage any infrastructure without the corresponding provider.
Trap Thinking resource types are built into Terraform Core rather than supplied by providers.
15 questions test this
- Reviewing a colleague's configuration, an engineer sees a `resource` block for `aws_s3_bucket` and, nearby, a `data` block for `aws_ami`, each beginning with the same `aws` prefix. What does that shar
- A developer new to Terraform assumes that resource types such as `aws_instance` and `google_storage_bucket` are keywords compiled into the Terraform CLI binary itself, the same way built-in language f
- A platform engineer opens the AWS provider's page on the Terraform Registry to plan a new configuration and notices it documents two separate catalogs: one titled "Resources" and another titled "Data
- An engineer adds a `data "aws_ami" "latest"` block to look up an existing image's ID so she can reference it in her configuration, then runs `terraform apply`. She wants to know what actually contacts
- An engineer only needs Terraform to read information from an external platform — never to create, update, or destroy anything there. A colleague claims Terraform cannot interact with a platform at all
- A team wants to manage an internal ticketing platform with Terraform, but no provider for it has ever been published on any registry and they will not write one themselves. Based on how Terraform is d
- A configuration manages three resources — `aws_instance`, `aws_vpc`, and `aws_s3_bucket` — and also declares a `data "aws_ami"` block to look up an image. A teammate asks how many separate providers m
- An engineer needs to manage a resource on Azure but has only declared and installed the AWS provider in her configuration. She reasons that since both are clouds, the installed provider should still b
- An engineer writes a resource block for the aws_instance type and runs `terraform apply`. She wants to understand which part of Terraform actually knows that the aws_instance resource type corresponds
- A team adds a `resource` block for a new provider's resource type but has not yet listed that provider in the configuration's `required_providers` block. Conceptually, why must the provider be declare
- A developer adds a `random_password` resource to generate a value and, because it touches no cloud service, assumes it is a built-in feature of the Terraform CLI that needs nothing installed. When `te
- A developer new to Terraform believes a `data` block is a built-in feature of the Terraform language that can look up information from a platform without installing any provider, unlike a `resource` b
- An engineer needs to look up the ID of a machine image that another team already created, so she can reference it in her configuration without creating, modifying, or destroying that image. Which prov
- A platform engineer writing her first Terraform configuration notices that resource types such as `aws_instance` and `azurerm_resource_group` are documented on the Terraform Registry rather than in Te
- A team currently manages only AWS resources with Terraform and now needs to manage DNS records on a SaaS platform for which an official provider is already published on the Terraform Registry. Concept
- Providers translate configuration into API calls
A provider translates the resources declared in configuration into the create, read, update, and delete API calls of its target platform, acting as the bridge between Terraform and the remote system's API.
Trap Thinking Terraform Core calls cloud APIs directly rather than through a provider plugin.
9 questions test this
- During `terraform apply`, an engineer's configuration declares a resource with several arguments, and Terraform creates the matching object on the cloud platform. She wants to understand what converts
- After `terraform apply` creates a new cloud object, the platform assigns it a server-generated identifier that was not present anywhere in the configuration, yet that identifier appears in Terraform's
- An engineer adds a `data "aws_ami" "latest"` block to look up an existing image's ID so she can reference it in her configuration, then runs `terraform apply`. She wants to know what actually contacts
- An engineer needs to manage a resource on Azure but has only declared and installed the AWS provider in her configuration. She reasons that since both are clouds, the installed provider should still b
- An engineer writes a resource block for the aws_instance type and runs `terraform apply`. She wants to understand which part of Terraform actually knows that the aws_instance resource type corresponds
- An engineer edits a managed resource's argument and runs `terraform apply`, and Terraform updates the real object; later she removes the resource block and `apply` destroys it. Throughout this create-
- A team adds a `resource` block for a new provider's resource type but has not yet listed that provider in the configuration's `required_providers` block. Conceptually, why must the provider be declare
- A platform engineer configures a `provider "aws"` block with a region and credentials, then wonders which part of Terraform actually uses those credentials to authenticate and issue requests to the AW
- During `terraform apply`, Terraform must issue create and update calls to a cloud platform's API to realize the resources declared in configuration. In Terraform's plugin architecture, which component
- Terraform Core ships with no resource types
Terraform Core ships with no built-in resource types; all resource types and data sources come from providers, which is why a configuration must declare its provider requirements.
- Resource type prefix selects the provider
Terraform infers which provider manages a resource from the prefix of the resource type name — for example
aws_instanceuses theawsprovider — unless the resource sets an explicitprovidermeta-argument.Trap Assuming the resource's name label (not the type prefix) determines the provider.
10 questions test this
- By default `resource "aws_s3_bucket" "logs"` is handled by the `aws` provider inferred from its prefix. An engineer needs this one bucket to use a different, non-default `aws` provider configuration i
- A previously empty module now contains a single resource, `resource "cloudflare_record" "www"`, plus a matching `required_providers` entry for `cloudflare`. A teammate runs `terraform init` for the fi
- A configuration declares both the `aws` and `google` providers and contains many resource blocks. A new engineer has valid AWS and Google Cloud credentials exported in their shell and asks how Terrafo
- A configuration mixes cloud resources with `resource "null_resource" "trigger"`. A reviewer claims `null_resource` is a built-in Terraform language construct that needs no provider, unlike the `aws_`
- An engineer writes the block `resource "google_storage_bucket" "aws_migration_target"` in a configuration that declares both the `aws` and `google` providers and sets no `provider` meta-argument. A re
- During a refactor an engineer edits a block from `resource "aws_instance" "app"` to `resource "google_compute_instance" "app"`, leaving the name label `app` unchanged, in a configuration that declares
- A team imports a module that declares the AWS provider under the conventional local name `aws`. A developer, assuming the name is only cosmetic, writes `resource "amazon_instance" "web"` expecting it
- To audit which resources a particular provider manages, an engineer wants to list every `resource` and `data` block handled by the `google` provider in a large configuration that sets no `provider` me
- A configuration contains `resource "aws_instance" "web"`, `resource "aws_s3_bucket" "assets"`, and `resource "aws_iam_role" "app"`, none of which set a `provider` meta-argument. A teammate asks how ma
- An engineer must pin one resource to a non-default provider configuration. The provider was declared with the local name `google` and a block carrying `alias = "europe"`. Which value for the resource'
- init installs plugins into .terraform
terraform initreads the configuration to determine the required providers and installs their plugin binaries under the.terraformdirectory of the working directory, recording the selections in the lock file.