Pulumi

Pulumi is an infrastructure as code tool that lets you define cloud resources in general-purpose programming languages — TypeScript, JavaScript, Python, Go, C#, Java, or YAML — instead of a domain-specific language. You get loops, functions, classes, types, package managers, IDE autocomplete, and unit tests, while Pulumi's engine computes a plan, shows a preview, and creates, updates, or deletes resources to match your program.

Pulumi supports AWS, Azure, Google Cloud, Kubernetes, and hundreds of other providers, including many bridged from the Terraform provider ecosystem. It's a strong fit for teams that want infrastructure written by the same engineers, in the same language, with the same testing habits as application code.

TL;DR

Quick Example

A TypeScript program that creates a private S3 bucket and a Lambda function with least-privilege access, configured per stack:

Core Concepts

Projects, Stacks, and State

A project is a directory with Pulumi.yaml and your program. A stack is an isolated deployment of that project, with its own Pulumi.<stack>.yaml config and state. State records what Pulumi manages; it can live in Pulumi Cloud (with history, locking, and RBAC) or a self-managed backend like S3 or Azure Blob Storage.

Resources, Inputs, and Outputs

Declaring new aws.s3.BucketV2(...) registers a desired resource. Many properties — IDs, ARNs, endpoints — aren't known until deployment, so they're Outputs. Pass Outputs directly to other resources (Pulumi tracks the dependency), or transform them with .apply(), pulumi.interpolate, or pulumi.all(). Don't try to read their values synchronously.

Component Resources

A ComponentResource groups child resources into a reusable abstraction with its own inputs and outputs — for example, a SecureBucket or ServiceWithDatabase class. Components can be shared as packages in your language's package manager or as multi-language components.

Config and Secrets

Stack configuration holds per-environment values. Values set with --secret are encrypted (with Pulumi Cloud, a passphrase, or a cloud KMS key) and stay encrypted in state. Pulumi ESC centralizes environments, secrets, and dynamic cloud credentials across stacks and tools.

Policy, Testing, and Automation

Providers and Imports

Native providers (like azure-native and google-native) track cloud APIs closely; bridged providers reuse Terraform providers. pulumi import brings existing resources under management, and pulumi convert translates Terraform HCL into a Pulumi program.

Best Practices

Keep Programs Declarative

Use language features for composition and loops, but avoid side effects like calling cloud APIs directly or reading mutable external state during a deployment.

Split Stacks by Lifecycle

Separate networking, data, and application stacks, and connect them with stack references so a routine app deploy can't touch the VPC.

Protect Critical Resources

Set protect: true on databases and buckets, and use retainOnDelete where losing data would be catastrophic.

Review Previews in Pull Requests

Run pulumi preview in CI and post the diff on the pull request, like terraform plan.

Encrypt Secrets and Use Short-Lived Credentials

Mark sensitive config as secret and use OIDC or ESC for cloud credentials rather than static keys.

Pin Provider Versions

Lock package versions so provider updates don't change behavior unexpectedly between runs.

Common Mistakes

Treating Outputs Like Plain Values

Using an Output in string concatenation produces [object Object] or a warning. Use pulumi.interpolate or .apply().

Creating Resources Inside apply

Resources declared inside callbacks don't appear in previews and make plans unpredictable.

Renaming Resources Without Aliases

Changing a resource's logical name makes Pulumi delete and recreate it. Use aliases to preserve identity during refactors.

Mixing Manual Console Changes

Out-of-band changes cause drift. Run pulumi refresh to detect them and reconcile in code.

Too-Clever Abstractions

Deep inheritance hierarchies and dynamic resource generation make infrastructure hard to review. Keep components simple and explicit.

Comparison

FAQ

What is Pulumi used for?

Provisioning and managing cloud infrastructure — networks, databases, Kubernetes resources, serverless functions — using programs written in general-purpose languages.

How is Pulumi different from Terraform?

Pulumi uses general-purpose languages with their tooling and testing, while Terraform uses HCL. Both use a plan-then-apply model and a state file, and both support many providers.

Where does Pulumi store state?

By default in Pulumi Cloud, which handles locking and history. You can instead use a self-managed backend such as S3, Azure Blob Storage, Google Cloud Storage, or the local filesystem.

Is Pulumi free?

The Pulumi CLI and SDKs are open source. Pulumi Cloud has a free individual tier and paid team and enterprise tiers; self-managed backends are free to use.

Can I migrate from Terraform to Pulumi?

Yes. pulumi convert translates HCL to a Pulumi program, and pulumi import or state import tools bring existing resources under Pulumi management without recreating them.

Related Topics

References