Open-source project
hashicorp/terraform-provider-aws avatar
hashicorp/terraform-provider-aws

Terraform AWS Provider: what it manages, how to install it, and where it stops

The AWS Provider enables Terraform to manage AWS resources.

11,104 stars10,393 forksGoMPL-2.0

At a glance

What is it?
The AWS Provider is the plugin that lets Terraform create and change AWS resources. This covers its versioning, the provider block, default tags, aliases, and the cases where it is the wrong layer.
Who is it for?
Adopt the AWS Provider if your infrastructure already lives in Terraform state and you want AWS resources under the same plan and apply cycle. Do not adopt it if you only need to call AWS APIs from application code, or if you want a generated one-to-one mapping of the Cloud Control API surface, which is what the AWSCC provider is for.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What the AWS Provider is for, and who ends up using it

Terraform on its own knows how to read configuration and build a dependency graph. It does not know what an AWS VPC is. The AWS Provider is the plugin that supplies that knowledge: it maps Terraform resource types such as aws_vpc or aws_s3_bucket onto AWS API calls, reads the results back, and stores them in state. The README states the purpose in one line: the provider "enables Terraform to manage AWS resources."

That puts it in the path of anyone who treats AWS infrastructure as a versioned artifact rather than a series of console clicks. Platform teams who hand out account-level building blocks, application teams who own their own ECS service and load balancer, and consultants who need a reproducible environment per client all end up writing the same provider block. The repository's examples directory shows the range: examples/ecs-alb, examples/eks-getting-started, examples/lambda, examples/networking, examples/asg. These are not toy snippets. They are working configurations for the kinds of stacks people actually deploy.

The provider is written in Go and released under MPL-2.0. It is not a service and has no runtime of its own. It is a binary that Terraform downloads, starts, and talks to over a plugin protocol.

How the provider talks to AWS, and how it gets its credentials

The provider is a separate process. Terraform starts it, sends it the resource graph, and receives back the API calls to make and the resulting state. Inside, the provider depends on the AWS SDK for Go v2, and go.mod lists one service package per AWS service, from accessanalyzer through to the rest of the catalog. That list is the clearest signal of the project's shape: coverage is per service, and a new AWS service means a new dependency and new resource code.

Credentials are not invented by the provider. It uses the standard AWS resolution chain, which is why the provider block can be as short as a region. Profiles, assumed roles, and region selection are all configuration on the provider, and the related searches around profiles, assume role, region, and aliases reflect how often those settings come up. If you run the same configuration against two accounts, you do it with two provider blocks and an alias, not by editing the region string.

One detail in go.mod is worth reading carefully. The file sets godebug tlsmlkem=0, with a comment explaining that the post-quantum X25519MLKEM768 key exchange mechanism causes errors with AWS Network Firewall. That is a deliberate, documented deviation from the Go default, and it tells you the maintainers are willing to pin transport behaviour when an AWS service cannot handle it.

Installing the provider and building a first VPC

You do not install this with go get or npm. Terraform resolves providers from the registry, and the required_providers block is where you declare it. The registry page linked from the README is the source of truth for the current version; the recent release tags in the repository are v6.66.0, v6.65.0, and v6.64.0, so the 6.x line is where the project currently sits. Pinning a version is the difference between a plan that reproduces next month and one that does not.

hcl
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

After writing that into a file and running terraform init, Terraform downloads the provider binary and records it in the dependency lock file. A plan at this point produces no changes because nothing has been declared yet. The provider block itself is not shown in the README, so the region argument is not reproduced here; the registry documentation covers it.

For a first resource, the repository ships working configurations rather than inline snippets. The examples/networking directory covers VPCs, subnets and routing, and examples/eks-getting-started and examples/ecs-alb show the provider in a full stack. The workflow is the same regardless of which example you start from: terraform init, terraform plan, terraform apply, and terraform destroy to tear it down.

Default tags and aliases: the two settings that scale past one file

Two provider-level features decide whether a large configuration stays readable.

Default tags let you attach a set of tags to every resource the provider creates, without repeating them in each resource block. That matters for cost allocation and for ownership metadata, where missing a tag on one resource is the kind of thing nobody notices until the bill arrives. The related searches show this is a common question, and it is a provider block setting rather than a per-resource one.

Aliases let one configuration address more than one AWS account or region. You declare a second provider block with an alias, then point a resource at it. This is how cross-account patterns work without splitting the codebase, and the repository's examples bear that out: examples/dx-gateway-cross-account-vgw-association and examples/network-firewall-cross-account-transit-gateway are both cross-account configurations. If you are building anything that spans accounts, aliases are the mechanism, and getting them wrong produces resources in the wrong account rather than an error.

The trade-off is that both features add indirection. Default tags can be overridden per resource, and an alias that is referenced in the wrong place fails quietly at plan time by targeting the default provider. Neither is hard, but neither is self-documenting either.

Where the AWS Provider is the wrong tool

The provider's coverage is per service and per resource, and that is its main limitation. A newly launched AWS feature does not appear the day it launches. Someone has to add the SDK dependency, write the resource, and ship a release. If your workflow depends on a feature that shipped last week, the provider may simply not have it yet, and no amount of configuration will change that.

The second limitation is state. The provider records what it created in Terraform state, and that state is the source of truth for planning. Resources created outside Terraform are invisible until imported, and a resource deleted in the console shows up as drift on the next plan. This is not a bug, but it is a real operational cost, and it is why teams that mostly click in the console find the provider frustrating.

The third case is a mismatch of layer. If you want to call AWS APIs from application code, the provider does nothing for you; you want the AWS SDK directly. If you want a machine-generated mapping of the Cloud Control API surface rather than hand-written resources, that is what the AWSCC provider is for. The two are not interchangeable, and the question of the difference between them is common enough that it appears in search data.

The AWSCC provider, and what actually differs

The AWSCC provider is the real alternative, and the difference is in how the resource types are produced. The AWS Provider's resources are written and maintained by hand against the AWS SDK for Go v2, one service package at a time, with the resource behaviour and schema chosen by the maintainers. The AWSCC provider is generated from CloudFormation resource schemas, so its resource types track the CloudFormation surface and appear closer to launch day.

The practical consequence is that the two do not cover the same set of resources, and a resource that exists in one may not exist in the other. The AWS Provider tends to have more opinionated, Terraform-native behaviour on the resources it does support, because a human wrote the schema. The AWSCC provider tends to have broader and faster coverage of new services, because generation is cheap. Neither is a superset.

Mixing them in one configuration is possible, and some teams do it for services the AWS Provider has not reached yet. That is a legitimate pattern, but it means two provider blocks, two state mappings, and two upgrade cadences to track.

Release cadence, upgrades, and the licence

The release tags in the repository show a fast cadence: v6.66.0 on 2026-09-21, v6.65.0 on 2026-09-16, v6.64.0 on 2026-09-09. The last push to the default branch was on 2026-09-21. Weekly releases are the norm, which means the upgrade cost is real and recurring rather than a once-a-year event.

The cost is mostly in version constraints. A constraint like ~> 6.0 accepts every 6.x release, so terraform init will pick up new versions and new resource behaviour without you asking. A tighter constraint such as = 6.66.0 freezes the provider but leaves you applying security and bug fixes by hand. Neither choice is free, and the right one depends on how much drift your team can absorb between applies.

Upgrading across major versions is the expensive case. Version 6.x is the current line, and the repository keeps a CHANGELOG.md and a .changelog directory, so the release notes are the place to look for breaking changes before bumping a constraint. The README does not document a rollback procedure for a provider upgrade, so plan for one before you need it.

The licence is MPL-2.0. That is a file-level copyleft licence: modifications to the provider's own source files carry obligations, while using the provider as a dependency in your Terraform configuration does not. This is a summary of the licence identifier, not legal advice; check the LICENSE file and your own counsel if you plan to redistribute a modified build.

Editorial conclusion

Adopt the AWS Provider if your infrastructure already lives in Terraform state and you want AWS resources under the same plan and apply cycle. Do not adopt it if you only need to call AWS APIs from application code, or if you want a generated one-to-one mapping of the Cloud Control API surface, which is what the AWSCC provider is for. Before you commit, verify three things: the exact provider version you will pin in required_providers, whether your region needs an aliased provider block, and whether the resources you need are documented on the registry page for that version. The repository's own ROADMAP.md is the place to check what the maintainers intend to change in the next quarter.

Frequently asked questions

What is the Terraform AWS Provider?

It is the plugin that lets Terraform manage AWS resources, maintained in the hashicorp/terraform-provider-aws repository and written in Go. Terraform downloads it as a provider binary and uses it to translate resource declarations into AWS API calls.

What is the difference between the Terraform AWS Provider and the AWSCC provider?

The AWS Provider's resources are hand-written against the AWS SDK for Go v2, while the AWSCC provider is generated from CloudFormation resource schemas. They do not cover an identical set of resources, so one is not a superset of the other.

How do I install the Terraform AWS Provider?

You declare it in the required_providers block with source hashicorp/aws and a version constraint, then run terraform init. Terraform downloads the binary from the registry; there is no separate install step.

How do I pin a specific version of the Terraform AWS Provider?

Set the version argument in required_providers. A constraint like ~> 6.0 accepts any 6.x release, while = 6.66.0 pins one exact version and requires manual bumps for fixes.

How do I use the Terraform AWS Provider with more than one AWS account or region?

Declare additional provider blocks with an alias and point resources at them. The repository's examples include cross-account configurations such as dx-gateway-cross-account-vgw-association.

What licence does the Terraform AWS Provider use?

MPL-2.0, as stated in the repository's LICENSE file. Using the provider from a Terraform configuration is not the same as redistributing a modified build of it.

Official sources

  1. hashicorp/terraform-provider-aws on GitHub
  2. License: MPL-2.0
  3. Project website
  4. README
  5. Releases
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hashicorp-terraform-provider-aws.svg)](https://hysenlabs.com/projects/hashicorp-terraform-provider-aws)
Community notes

Community notes