How can you improve the state of your infrastructure automation?

➡️ Take the Self-Assessment

General

What is Pulumi? Key Concepts and Features Overview

What is Pulumi

Subscribe to our Newsletter

Mission Infrastructure newsletter is a monthly digest of the latest posts from our blog, curated to give you the insights you need to advance your infrastructure game.

In the last years, teams have accelerated their dependency on the public cloud. Whether you are scaling an already existing product or building a new product that is native to the cloud, chances are you’ve felt that there has got to be a better way to build cloud infrastructure. There is. Enter Pulumi.

What we’ll cover in this article:

  1. What is Pulumi?
  2. How does Pulumi work?
  3. Key features of Pulumi
  4. Alternatives to Pulumi
  5. Concerns with Pulumi
  6. So why not Pulumi?

What is Pulumi?

Pulumi is an infrastructure-as-code (IaC) platform for full-stack developers and cloud engineers who want to use a general-purpose programming language, such as TypeScript, Python, Go, and C#, for their cloud resources. 

Unlike domain-specific languages used by tools like Terraform, Pulumi integrates directly into application codebases, supporting testing, abstraction, and reuse. It works across major cloud providers such as AWS, Azure, and Google Cloud, offering flexibility for multi-cloud environments.

How does Pulumi work?

Pulumi is an ecosystem of components that all work together. At a high level, the components include provider SDKs, CLI, and service backend. 

SDKs are installable packages your program consumes using the respective language’s package registry. You probably work with them already. Pulumi supports the following programming and markup languages for writing infrastructure as code:

  • TypeScript
  • JavaScript
  • Python
  • Go
  • .NET languages (C#, F#, and VB)
  • Java
  • YAML

This means you can use general-purpose code to create cloud resources such as variables, loops, functions, classes (well, at least in OOP), strong-type support, code reuse, and everything else you can do in those programming languages. 

It also gives you the option to maintain a homogeneous codebase if that’s important to your team. For example, a team working on a C# .NET app may be interested in implementing their cloud infrastructure also in C# .NET. Or a team working on a React-based app strong in JS and the Node.js ecosystem may want to use JS for their cloud infrastructure too. Let’s examine each of those components in detail:

Provider SDKs

There are over 75 providers, and new ones are being added regularly. You can also contribute new ones. 

All SDKs are available in all supported languages. Extension libraries are typically not supported in every supported language because they are typically authored manually and in a language based on community demand. 

For example, the official Pulumi EKS is a popular Pulumi component library supported in JS/TS and Python. But wait! The EKS library is also a great example of how you can author and use multi-language components in the Pulumi ecosystem. More on multi-language components later…

CLI

The Pulumi CLI is one of the ways users can run previews and updates on their infrastructure programs. The CLI supports several powerful commands to mutate the state of your cloud resources. 

There is another powerful way to automate the execution of your Pulumi apps.

Service backend

The Pulumi Service backend is the default state storage service for all Pulumi projects. This means that every time you update your cloud resources using Pulumi, the service stores a snapshot of the state of your resources known as the checkpoint. The checkpoint allows you to confidently make changes to your infrastructure.

Example: How to use Pulumi

As mentioned before, several components work together in the Pulumi ecosystem to mutate cloud resources. Let’s examine this with an example: 

Say we want to create a Bucket using DigitalOcean Spaces. We’ll use JS as an example for demonstration purposes:

const foobar = new digitalocean.SpacesBucket("foobar", {
    region: "nyc3",
});

// Export the bucket name as an output. This is a familiar concept for JS developers.
// A similar construct exists in all of the supported languages so you can export
// outputs regardless of the language you choose.
module.exports = {
    bucketName: foobar.name
};

Note that I’ve skipped the part about bootstrapping a new project. Just as with any other new app, Pulumi requires some minimal project setup. This can be done easily with pulumi new, which lets you pick a template to start from.

To create the Bucket in a DigitalOcean account, we’ll need an account and an access key for Spaces, so that Pulumi can authenticate on our behalf to mutate resources. We’ll assume that a token is created and configured correctly. 

Now that we have authentication with DigitalOcean, we can run pulumi preview from the terminal (or an IDEs integrated terminal.)

pulumi preview

The Pulumi CLI “processed” the index.js file and generated a graph of the resources that needed to be created (or deleted, updated…or do nothing if nothing has changed). The graph is simple in this case. We just want to create a single bucket. 

Behind the scenes, the CLI uses this graph to calculate the set of CRUD operations using the DigitalOcean API.

Running pulumi up -y will auto-approve Pulumi to go ahead and create the bucket.

pulumi up -y

Key features of Pulumi

Using a general-purpose programming language means all language features are implicitly Pulumi’s features. Aside from that, there is a rich feature set to help with an ever-evolving cloud infrastructure landscape.

1. ComponentResources

ComponentResources are resources that encapsulate multiple child resources. In simple terms, think of them as a class that you can create that lets you represent several related resources as a single unit. 

For example, you might want to create a component that handles setting up an S3 bucket with replication in a secondary region for disaster recovery scenarios. 

You could create a component that accepts the bucket name as input but creates two buckets behind the scenes — one in the primary region and the other in the failover region. Actually, there is already a component for that.

2. StackReferences

As your infrastructure evolves, you may want to create multiple stacks, with certain stacks needing to consume the outputs exported by other “upstream” stacks. This is easy to do with StackReferences

Here is a quick example:

const docker = require(“@pulumi/docker”);
const other = new pulumi.StackReference("acmecorp/infra/database");
const dbEndpoint = other.getOutput("dbEndpoint");

// Build a container image for an API service that uses the DB endpoint.
const api = new docker.Image(“api”, {
    build: {
        context: “”,
        env: {
DB_ENDPOINT: dbEndpoint
        }
    }
});

3. Dynamic providers

Although limited to specific languages, dynamic providers can serve as a sort of escape hatch for when you need to mimic the CRUD lifecycle of a resource, but there is no official provider for that resource. A great example of dynamic providers would be to answer the question, “how do I configure a newly provisioned VM?”. 

4. Automation API

When we discussed the CLI, we mentioned it is one way to run Pulumi apps on users’ machines and in CI/CD pipelines. The Automation API allows users to programmatically invoke CLI operations, unlocking a whole other set of possibilities. Pulumi’s customers have fully exploited this feature to enable advanced deployment scenarios for their organizations.

Alternatives to Pulumi

Alternatives vary based on which aspects of Pulumi you would like to compare.

Other general-purpose programming language tools

AWS CDK is superficially similar to Pulumi. However, it is limited to… well, AWS. It is also fundamentally different in how it works behind the scenes. As a user provisioning resource on AWS, you may not need to worry about the implementation details of the technology for your use case.

AWS CDK vs. Pulumi

CDK Pulumi
Supports popular languages Supports popular languages
Transpiles to CloudFormation template Doesn’t transpile to any proprietary format
Cannot natively provision non-AWS resources Can use any of the 70+ providers as well author your own for edge-cases using Dynamic Providers or contribute your own
Can create custom encapsulations using CdkContructs that create other AWS resources or Constructs Can create custom encapsulations using ComponentResources that can
Has a registry showcasing community-supported as well as AWS-supported Constructs in the Construct Hub Has a registry showcasing community-supported as well as Pulumi-supported components and packages in the Pulumi Registry

Other infrastructure-as-code tools

IaC isn’t restricted to general-purpose programming language-based tools. In fact, one of the most common IaC tools that Pulumi is often compared with is Terraform. HashiCorp’s Terraform existed in the IaC space well before Pulumi was created. 

If you look deeper, Pulumi extends (the official word is “bridge”; however) many of Terraform’s providers as well as native providers that are direct implementations from Open API specs. They are conceptually similar in that both tools want you to think about everything in the cloud as a “resource.” The resource model drives the core of your infrastructure state. Every resource has a CRUD lifecycle.

Though similar in concept, they are very different. The fundamental difference is that the developer  can choose the language that suits them and their team. Of course, there are other differences.

Terraform vs. Pulumi

Terraform Pulumi
Uses proprietary but open-source language HCL which stands for HashiCorp Configuration Language Supports popular open-source, general-purpose programming languages
HCL is a type of domain-specific language None of the supported languages are DSLs
By definition, DSLs are limited in their language feature set Out-of-box support for language-level features that are not custom-made by Pulumi
Has a registry showcasing community-supported as well as Terraform-supported Constructs Has a registry showcasing community-supported as well as Pulumi-supported components and packages
No escape-hatch like functionality to create self-managed resources in cases where a provider doesn’t support a feature Dynamic Provider feature to model the CRUD lifecycle of custom one-off resources

Check out a detailed comparison of Pulumi vs. Terraform.

OpenTofu vs. Pulumi

OpenTofu is an open-source IaC tool for provisioning and managing cloud and on-prem infrastructure. It originated as a community-driven fork of Terraform following HashiCorp’s licensing changes.

OpenTofu allows users to define infrastructure declaratively using configuration files, ensuring consistent, repeatable deployments. It supports major cloud providers and integrates with CI/CD pipelines for automated infrastructure management.

Because it remains open-source under a permissive license, OpenTofu appeals to organizations seeking transparency, vendor neutrality, and community-driven development.

OpenTofu focuses on simplicity, predictability, and a Terraform-compatible workflow, making it ideal for teams already familiar with Terraform. Pulumi offers more flexibility and integration with software development practices, which may be appealing to developers who prefer using familiar languages and tooling.

Other alternatives

Some of the biggest cloud providers have their own proprietary tools for implementing cloud infrastructure.

  • AWS CloudFormation — A JSON/YAML-based authoring experience for provisioning AWS resources. AWS CDK, which lets you author infrastructure for AWS resources, transpires to a CloudFormation template and then deploys the infrastructure using CloudFormation.
  • Azure Bicep — Microsoft Azure’s version of a DSL IaC tool, it is meant to replace ARM templates.
  • GCP Deployment Manager — A deployment service whose primary configuration language is YAML. In some cases, documentation is scarce, and feature support is very limited.

Concerns with Pulumi

Let’s examine a few concerns developers have expressed about adopting a fundamentally new way to implement cloud infrastructure with a tool like Pulumi.

Deciding on a language

Picking a language in a new tool can feel like a pretty drastic one-way decision. Fortunately, Pulumi interoperates with the supported languages. Delving into how multi-language components work deserves its own post.

Some may say that being stuck with a general-purpose programming language is still better than having to learn a cloud provider’s DSL (templates or otherwise.) Learning a new language or technology has a cost. That cost is especially high when members of your team may not spend a lot of time with infrastructure on a daily basis.

DSL is easier/quicker

One of the strengths of any DSL is its succinctness. It’s one of the reasons why DSLs are great for all types of configuration management. I think this is a matter of perspective. Developer skills are highly varied, and everyone has their own sweet spot of languages with which they are comfortable. I mean, why would we need anything other than JS? Just kidding. 

On a more serious note, many developers are indeed more comfortable using DSL-based technologies such as Terraform for their cloud automation needs. Many others want something familiar and can be supported by any developer with language familiarity.

State storage

One of the nice features of Pulumi is that the Pulumi Service stores the state for your infrastructure, by default. Right from the moment you run pulumi stack init <stackName>. But if things change and you would like to manage the state on your own, Pulumi does support self-managed backends too. 

That means you could export your state and store it on your own inside one of the supported self-managed backends such as AWS S3, Azure Storage or GCS.

New technology/Never heard of it

Pulumi emerged in 2018, and several well-known organizations use it. During my time at Pulumi, I encountered several teams that built complex cloud infrastructure installations spanning several cloud providers. Your use case doesn’t have to be complex to use Pulumi. Many start simple but grow organically and don’t realize the growth was facilitated by Pulumi.

See also: Pulumi Pricing – Editions Overview.

Spacelift support for Pulumi

Once you’ve got your Pulumi stack configured, you might be wondering, well, now what? It is pretty typical to wire up a CI/CD pipeline to run the same Pulumi commands you ran on your machine. Pulumi integrates really well with many CI/CD services.

This is where Spacelift excels. Spacelift is the most flexible management platform for IaC. It provides excellent capabilities to automate running your Pulumi stacks, so you don’t have to configure your own CI pipelines — especially if you have several stacks and want to connect them together, and it does not stop there.

With Spacelift, you get:

  • Policies to control what kind of resources engineers can create, what parameters they can have, how many approvals you need for a run, what kind of task you execute, what happens when a pull request is open, and where to send your notifications
  • Stack dependencies to build multi-infrastructure automation workflows with dependencies, having the ability to build a workflow that, for example, generates your EC2 instances using Terraform and combines it with Ansible to configure them
  • Self-service infrastructure via Blueprints, or Spacelift’s Kubernetes operator, enabling your developers to do what matters – developing application code while not sacrificing control
  • Creature comforts such as contexts (reusable containers for your environment variables, files, and hooks), and the ability to run arbitrary code
  • Drift usually occurs when people manually modify resources outside of Pulumi. Spacelift can detect it automatically and optionally remediate it.

If you are searching for the right product to manage your OpenTofu, Terraform, Pulumi, Ansible, CloudFormation, Kubernetes, and Terragrunt, Spacelift is the answer.

orbica logo in white

AI-powered environmental monitoring platform Orbica wanted to focus on bringing its geospatial domain expertise to market — not learning new tools. Spacelift was the most cost-effective and flexible option, supporting multiple frameworks, including OpenTofu and Pulumi — not just Terraform. This flexibility mitigated the risk of vendor lock-in and sprawl as Orbica’s tech stack expanded. The integrated Terraform registry also made it easier to manage a catalog of infrastructure modules to construct better abstractions and further improve the DX.

So why not Pulumi?

Even if you know the language well, cloud infrastructure is complex. (Want to create a private subnet with a NAT gateway? Wait, what’s a NAT, and why do I need a private subnet? Exactly.) 

Pulumi helps reduce some of that complexity by removing the cognitive load associated with familiarizing yourself with a DSL or a template system. 

In some cases, packages like the Crosswalk for AWS or the Pulumi Cloud framework actually help address the complexity associated with cloud infrastructure, but they do not eliminate it. You’ll discover that as your cloud infrastructure needs evolve, Pulumi’s capabilities scale well with that.

What are the main advantages of using Pulumi?

Pulumi is well-suited for teams seeking a programmable approach to cloud infrastructure with broad provider support. The general main advantages include:

  • Multicloud support: It works across AWS, Azure, GCP, Kubernetes, and others through a unified model.
  • Use of real programming languages: It allows conditionals, loops, abstraction, and reuse using familiar language features.
  • CI/CD and version control integration: It supports modern DevOps workflows with native integrations.
  • Flexible state management: It offers both a managed service and self-hosted options for storing infrastructure state.

Key points

Pulumi is an open-source infrastructure as code (IaC) tool for provisioning, managing, and deploying cloud infrastructure using general-purpose programming languages. Instead of writing YAML or JSON (like in Terraform or CloudFormation), you can use actual code logic (e.g., loops, conditionals) to define infrastructure, making it more reusable and maintainable.

Hopefully, this post has given you many reasons to try Pulumi. To get you started, check out the Pulumi and Spacelift documentation.

If you want to test drive Spacelift for free, create a free trial account or book a demo with one of our engineers.

Cost-effective Pulumi Cloud alternative

Spacelift is a highly cost-effective Pulumi Cloud alternative that works with Pulumi, Terraform, and many other IaC frameworks. It supports self-hosted on-prem workers, workflow customization, drift detection, and much more.

Learn more

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide