Skip to main content

Pulumi Ep 10: Using Native Providers (AWS Classic vs AWS Native)

Rachmat Hidayat
Author
Rachmat Hidayat
Learn & sharing insights on TypeScript, Go, Kubernetes, DevOps, DevSecOps, SRE, Platform Engineering, AI/ML Engineering, and MLOps.
pulumi - This article is part of a series.
Part 10: This Article
For years, the dirty secret of the Infrastructure as Code industry was that almost every tool (including Pulumi’s early versions) relied on Terraform’s open-source Go providers under the hood. Pulumi wrote a “Bridge” to translate TypeScript into Terraform’s internal schema. Today, that is changing. Enter Pulumi Native Providers.

1. The Classic Bridged Provider (@pulumi/aws)
#

Everything we have deployed so far has used the @pulumi/aws package. This is a Bridged Provider.

How the Bridge Works
#

  1. You write new aws.s3.Bucket("my-bucket") in TypeScript.
  2. The Pulumi Engine receives this intent.
  3. Pulumi hands the intent to the Pulumi-Terraform Bridge.
  4. The Bridge translates your TypeScript object into the exact Go struct expected by the hashicorp/aws Terraform Provider.
  5. The Terraform Provider makes the actual REST API call to AWS.

Why does this matter?
#

Because the Classic provider depends on the Terraform community to maintain it. When AWS releases a brand new service (e.g., a new Bedrock AI model), HashiCorp engineers must manually write thousands of lines of Go code to support it. This can take weeks or months. You are entirely at the mercy of the maintainers’ backlog.


2. The AWS Native Provider (@pulumi/aws-native)
#

In 2021, AWS released the Cloud Control API. This is a unified, standard API for all AWS services. Simultaneously, Pulumi built the AWS Native Provider.

The Native Provider completely bypasses Terraform. Instead of waiting for humans to write Go code, the Native Provider is automatically generated by software directly from the AWS CloudFormation Resource Specification.

The Benefits of Native
#

  1. Zero-Day Support: When AWS releases a new service, it is instantly available in @pulumi/aws-native on the exact same day. No waiting for community PRs.
  2. Speed: Bypassing the Terraform translation layer makes deployments noticeably faster.
  3. Accuracy: The property names in the Native provider match the official AWS documentation exactly (e.g., InstanceType instead of instance_type).

3. Practice: Classic vs Native Syntax
#

Let’s look at the difference in code.

First, install the native provider:

npm install @pulumi/aws-native

Now, let’s provision an S3 bucket using both providers in the same file to compare the syntax.

import * as awsClassic from "@pulumi/aws";
import * as awsNative from "@pulumi/aws-native";

// 1. The Classic (Bridged) Bucket
const classicBucket = new awsClassic.s3.Bucket("classic-bucket", {
    // Notice the lowercase, snake_case style properties inherited from Terraform
    forceDestroy: true,
});

// 2. The Native Bucket
const nativeBucket = new awsNative.s3.Bucket("native-bucket", {
    // Notice the exact 1:1 mapping with the AWS API documentation (PascalCase!)
    bucketName: "my-native-bucket",
    publicAccessBlockConfiguration: {
        blockPublicAcls: true,
        ignorePublicAcls: true,
    }
});

Notice the properties in the awsNative resource. They are exactly identical to what you see if you read the official AWS CloudFormation documentation.

If AWS adds a new property to the S3 API tomorrow called QuantumEncryptionSettings, you simply upgrade your NPM package and write quantumEncryptionSettings: { ... }. It just works.


4. Should I switch to Native today?
#

The obvious question is: If Native is better, why isn’t it the default?

As of right now, the transition is still ongoing in the industry.

Stay with Classic if:
#

  1. You have massive amounts of existing infrastructure already deployed using @pulumi/aws. Migrating state from Classic to Native is technically complex and requires manual state file manipulation (pulumi state rm and pulumi import).
  2. You rely heavily on “Helper” functions. The Terraform provider often includes custom Go logic to make complex AWS APIs easier to use. The Native provider is a strict, literal 1:1 mapping of the raw AWS API, which can sometimes be more verbose to write.

Use Native if:
#

  1. You are starting a brand new project today (Greenfield development).
  2. You absolutely need a brand new AWS service that hasn’t been implemented in Classic yet.
  3. You are building Azure infrastructure (The @pulumi/azure-native provider is fully mature and is the default standard for Azure development in Pulumi).
Tip

You can mix and match! It is perfectly safe to use @pulumi/aws for your core VPC, and @pulumi/aws-native for a brand new Machine Learning service in the exact same index.ts file.


Conclusion & Next Steps
#

You now understand the internal mechanics of Pulumi’s provider ecosystem. You know how to leverage zero-day AWS features using @pulumi/aws-native, and you understand the historical context of the Terraform Bridge.

This concludes the Intermediate tier! You are now capable of building robust, modular, and multi-cloud architectures.

But writing infrastructure is only half of Platform Engineering. The other half is ensuring that infrastructure is actually correct, secure, and compliant before it ever reaches the cloud.

In Episode 11: The Automation API, we enter the Advanced Tier. We will learn how to embed the Pulumi Engine directly into a custom Node.js application to build internal Developer Portals and SaaS platforms!

pulumi - This article is part of a series.
Part 10: This Article