Pulumi’s AWS providers are not just wrappers; they represent fundamentally different approaches to managing AWS resources, with AWS Native being the modern, idiomatic choice for most use cases.
Let’s see what this looks like in practice. Imagine we want to create an S3 bucket.
AWS Classic (Pulumi AWS Provider)
import * as aws from "@pulumi/aws";
const bucketClassic = new aws.s3.Bucket("my-classic-bucket", {
acl: "private", // Example property
});
export const bucketNameClassic = bucketClassic.id;
This code uses the older, more established @pulumi/aws provider. It abstracts away some of the direct AWS API nuances, offering a Pulumi-specific resource model.
AWS Native (Pulumi AWS Native Provider)
import * as aws_native from "@pulumi/aws-native";
const bucketNative = new aws_native.s3.Bucket("my-native-bucket", {
acl: "private", // Example property
bucketName: "my-unique-native-bucket-name", // Often requires explicit name
});
export const bucketNameNative = bucketNative.bucketName;
This uses the newer @pulumi/aws-native provider. Notice the aws_native namespace. This provider aims to mirror the AWS CloudFormation resource model more closely, meaning if a resource exists in CloudFormation, it likely exists in AWS Native.
The core problem AWS Native solves is the divergence between the Pulumi AWS provider’s resource model and the actual AWS resource model. Over time, the @pulumi/aws provider introduced its own abstractions and sometimes fell behind AWS’s rapid feature releases. This meant that new AWS features or specific configurations might not be immediately available or might be exposed in a less direct way. AWS Native, by aligning with CloudFormation, ensures that you’re always working with the most up-to-date and comprehensive set of AWS resources as defined by AWS itself. It provides a more direct mapping, reducing the "translation layer" and offering better consistency with AWS documentation and other IaC tools that rely on CloudFormation.
Internally, @pulumi/aws uses a Pulumi-specific schema and resource implementation. When you define an aws.s3.Bucket, Pulumi translates your desired state into the necessary AWS API calls. @pulumi/aws-native, on the other hand, largely uses code generation directly from the CloudFormation resource specification. This means its schema is a near-perfect reflection of what CloudFormation supports. When you define an aws_native.s3.Bucket, Pulumi (via the AWS Native provider) translates this into CloudFormation-compatible API calls, often creating a CloudFormation stack behind the scenes for complex resources, or directly calling AWS APIs for simpler ones. This underlying mechanism allows it to track AWS features much more closely.
The primary lever you control is the choice of provider. For new projects, or when adopting new AWS services, @pulumi/aws-native is generally recommended. If you have existing infrastructure managed by @pulumi/aws, migrating can be a project in itself, but it offers the benefit of direct access to the latest AWS capabilities. You can also use both providers within the same Pulumi project, though this is usually only for specific migration strategies or when a resource is only available in one provider.
One critical difference often overlooked is how resource naming and unique identifiers are handled. In @pulumi/aws, Pulumi often generates a unique physical ID for resources like S3 buckets if you don’t provide one explicitly, simplifying initial setup. With @pulumi/aws-native, because it maps more directly to CloudFormation, you’ll frequently find yourself needing to provide explicit, globally unique names for resources like S3 buckets or DynamoDB tables upfront in your configuration, as CloudFormation often requires this. This is because the underlying CloudFormation resource specification dictates these requirements, and the native provider adheres to them.
The next hurdle you’ll encounter is understanding the naming conventions and slight differences in property names between the two providers, which can require careful review when migrating or referencing AWS documentation.