Learn Pulumi in 5 minutes + See us speak in Prague! πŸ‡¨πŸ‡Ώ


Hey Reader πŸ‘‹πŸ½

We've been talking a lot about how great SST's switch to Pulumi was, and many of you have asked us how to use plain Pulumi directly.

So today, we're sharing our quick guide to Pulumi - a tool we're really excited about since it lets us build infrastructure with languages we already know and love. No more learning weird syntax - just TypeScript, Python, or whatever we're comfortable with!

We spent the last few days playing with it, and here's what we've learned...

AWS Community Day Prague 2025 πŸ‡¨πŸ‡Ώ
Join us at AWS Community Day Prague 2025, a friendly gathering of AWS enthusiasts and experts for a day of learning and fun.
We are both presenting two different talks on that day!

Don't miss our talks:

β€’ πŸ”„ Sandro: "EDA for the real world"
Learn best practices from building an event-driven architecture in a startup. From 0 to 1 million events a month
β€’ πŸ“Š Tobias: "Considerations for AWS-native observability before jumping into a >$100k/yr 3rd party tool"
Discover cost-effective observability strategies using AWS native solutions

Why come?

β€’ πŸ‘₯ Meet other AWS fans in a relaxed atmosphere
β€’ πŸ’‘ Learn practical tips you can use right away
β€’ 🍻 Enjoy Prague and hang out with the community
Register Now 🎟️
"Come for the AWS knowledge, stay for the community!" ✨
❀️ Not sponsored β€” we're sharing this to support the amazing organizers of AWS Community Day Prague.
Want to sponsor our newsletter? Contact us for sponsorship opportunities!

Introduction

Pulumi is a modern Infrastructure as Code platform. Like other tools (e.g., Terraform, CloudFormation, CDK), you can define your whole infrastructure in code.

One of the main differences is that Pulumi is not bound to AWS only. You can also deploy infrastructure to Azure, GCP, Cloudflare, etc.

​

Furthermore, Pulumi allows you to use your favorite programming language. This means you can use Python, TypeScript, Go, JavaScript, and more.

In this article, we will look at how to get started with Pulumi. At the end, you'll know everything you're set up to start building your own infrastructure.

Key Concepts

Like Terraform, Pulumi is a declarative tool. This means we'll describe our desired state of our infrastructure. Pulumi will then take care of creating this state through actions.

​

On the host, we'll write our code in a programming language of our choice. Pulumi will then compute this into a plan, which is a list of actions that need to be taken to reach the desired state.

This means it will calculate which resources need to be

  • created,
  • updated,
  • or deleted.

The state is later stored in a stack. This stack can live in a remote or local directory.

For serious projects, it's a requirement to use a remote stack, as otherwise, collaboration is not possible.

Projects

For Pulumi, every folder that contains a Pulumi.yaml file is considered a project. If there's no Pulumi project yet, you can create one by running pulumi new.

As we've learned, the supported runtimes are nodejs, python, dotnet, go, java and yaml.

The project file itself is a simple, short YAML file:

When using NodeJS, by default, Pulumi will use TypeScript. You can change this by setting options.typescript to false.

With NodeJS-based projects, we'll also need a package.json file. This way, we can install dependencies that are needed for our project.

Also worth noticing, everything you refer to on the local filesystem needs to be relative to the project's root.

Stacks

Stacks are a way to manage different environments. For example, we can have a dev and a prod stack.

Each stack can have its own configuration. When we create a new stack, Pulumi will also create a Pulumi.$STACK_NAME.yaml file.

This file can contain any configuration that we want to use for this stack.

You can set the configuration properties via the CLI or directly in the YAML file.

Inside your infrastructure file, e.g., your index.ts. In the case of a NodeJS project, you can access your configuration properties and your stack name at any time.

The config object also has other methods, like requireObject which allow us to require a configuration object. If it's not set, it will throw an error.

Resources

Resources are the main building blocks in Pulumi. They make up your infrastructure.

In case of AWS, a resource is a single AWS resource, like a VPC, a security group, an EC2 instance, etc.

There are two subclasses of resources:

  1. CustomResource: a cloud resource managed by a resource provider, e.g., AWS.
  2. ComponentResource: a resource that is composed of other resources, e.g., a VPC and an EC2 instance. These are the higher building blocks that are used to create more complex infrastructure via composition.

Higher building blocks are also called components. They are very useful when we want to create reusable infrastructure.

In the example above, we're having a component that is composed of resources needed to run a containerized application in Fargate.

Inputs and Outputs

Now to one of the most important concepts in Pulumi: inputs and outputs.

All resources that Pulumi accepts are called inputs. For example, the aws.lambda.Function resource accepts inputs like name, handler, runtime, etc.

Pulumi will later translate this into a plan and map the inputs to the API call's parameters.

Outputs are the other way around. They are the values that are returned by a resource.

For example, the aws.lambda.Function resource returns an arn or name output.

The output is calculated when the resource is created. Pulumi can't know it beforehand, as it's a runtime value.

Nevertheless, we can still access it via the arn output property.

Now, here comes the magic of Pulumi: We can also use this output as an input for other resources.

This way, we can create a log group for our Lambda function. We don't need to hardcode the name of the log group, as it's dynamically created by Pulumi.

If we change the name of the Lambda function, the log group would automatically be renamed to match the new Lambda function's name.

If you've ever worked with CDK or CloudFormation you know how big of a hassle this can be. Pulumi makes this one super easy!

Secrets

Secrets are a way to manage sensitive information, like passwords, API keys, etc. This way, you don't need to work with plain text secrets in your Pulumi configuration files.

With the CLI, we can easily encrypt secrets and push them to our configuration files.

This will encrypt the secret and save it to the configuration file.

By default, Pulumi will use a key that is managed by the Pulumi Cloud. Alternatively, you can also use other key management systems, like AWS KMS, Azure Key Vault, and Google Cloud KMS. This way, the keys are managed by you or your organization.

Inside our code, we can access the secret via the Config object.

The great thing here: Pulumi will never print the secret value to the console. Even if we decide to explicitly print the secret value, it will be masked.

State Management and Backends

When Pulumi creates a resource for you, it needs to store metadata so it knows what it created. This metadata is stored in the state file.

This state file should live in a remote backend; otherwise, collaboration will be a pain.

Luckily, Pulumi is very flexible when it comes to state management.

We can choose where to store the state file. Options include but are not limited to:

  • AWS S3
  • Microsoft Azure Blob Storage
  • Google Cloud Storage

Alternatively, you can also use the Pulumi Cloud as a backend.

When you decide to use a remote backend, you always need to log in before using the CLI.

Hands-On

Now that we know the key concepts, let's bring them to life.

What we'll do:

  1. Configuring Pulumi so that it's able to deploy to AWS.
  2. Creating a new project and stack.
  3. Provisioning a simple S3 bucket via the Pulumi starter template.
  4. Deploying everything.
  5. Destroying the stack and cleaning up.

Prerequisites and Installation

Before we start, we need to install Pulumi.

  • 🍏 macOS: We can simply install Pulumi via Homebrew.
  • 🐧 Linux: We can use curl to run the installation script for the latest version via curl -fsSL https://get.pulumi.com | sh.
  • πŸͺŸ Windows: by using PowerShell, we can use chocolatey to install Pulumi via choco install pulumi.

Choosing our Programming Language

As mentioned earlier, Pulumi doesn't come with its own language. Instead, we can use our favorite programming language.

Supported languages are:

  • Python
  • TypeScript
  • Go
  • JavaScript
  • C#
  • Java

You can also make use of YAML, but I don't recommend it.

In this guide, we'll use TypeScript.

Setting up our AWS Access

We'll now install the AWS CLI. When using macOS, you can use homebrew via brew install awscli to get the latest version. For Linux and Windows, there's a similar process.

Configuration of our Credentials

You need to be authenticated and authorized to access your account via the AWS CLI. This requires you to have an Access Key ID and Secret Access Key.

Let's head over to your user's security credentials settings so we can create a pair of those if you haven't done this already.

Security Best Practice: While using long-term access keys is convenient for this tutorial, it's recommended to use temporary session tokens with Multi-Factor Authentication (MFA) for enhanced security in production environments. Learn more in our guide on AWS Authentication Best Practices.

We'll select the Command Line Interface (CLI). The AWS console may note that it's recommended to make use of the IAM Identity Center to access the AWS CLI.

Make sure to save your Secret Access Key, as you can't display it again.

Now we can jump back into our terminal and run aws configure , which will prompt us for our previously created Access Key and Secret Access Key. It will also ask for a default region, e.g., us-east-1, and the default output format, e.g. json.

If you've set up everything properly, you should be able to get a few details of your account and user by running aws sts get-caller-identity.

Now we're ready to start building!

Creating a New Project and Stack

We'll store our state in an Amazon S3 bucket. Let's create that bucket first

Now, we can already log in to Pulumi.

Now, we can create a new project by using the pulumi new command and using the aws-typescript template.

​
You'll be asked a lot of questions while going through the process, including:

  • The name of the project
  • Project description
  • Stack name
  • Phrase to protect the secrets
  • Your desired package manager
  • The AWS region to deploy to

Afterward, you'll see a success message like this:

​
Our project is now ready to go! πŸŽ‰

Let's have a look at our index.ts file.

It's a very minimalistic example, but it's enough to get us started.

Now, we can already perform an initial deployment with pulumi up.

Pulumi will now translate our TypeScript code into a plan.

As we can see, Pulumi detected that we want to create a new S3 bucket. We can now decide whether we want to apply this plan or not (this can also be skipped by using the --yes flag).

Let's confirm the plan and apply it.

Now, we can head over to our S3 bucket and see that it's been created.

Now, we can destroy the stack and clean up with pulumi destroy.

​
That's it already! πŸŽ‰

You've learned the key concepts of Pulumi and how to create a new project and stack.

Summary

That's it for today! We hope this quick intro to Pulumi gives you a taste of how simple infrastructure-as-code can be when you use your favorite programming language.

What do you think about Pulumi? Hit reply and let us know if you're already using it or planning to try it out. We'd love to hear your experiences!

And if you're anywhere near Prague this week, come hang out with us at AWS Community Day - first round's on us! 🍻

Happy building,

Sandro & Tobias
​

​

​

​Tobias Schmidt & Sandro Volpicella & from AWS Fundamentals​
​
Cloud Engineers β€’ Fullstack Developers β€’ Educators

You're receiving this email because you're part of our awesome community!

If you'd prefer not to receive updates, you can easily unsubscribe anytime by clicking here: Unsubscribe

​

Our address: Dr.-Otto-Bâßner-Weg 7a, Ottobrunn, Bavaria 85521

AWS for the Real World

Join our community of over 9,300 readers delving into AWS. We highlight real-world best practices through easy-to-understand visualizations and one-pagers. Expect a fresh newsletter edition every two weeks.

Read more from AWS for the Real World

Newsletter Header AWS FOR THE REAL WORLD ⏱️ Reading time: 8 minutes πŸŽ“ Main Learning: Migrating from Edgio to CloudFront ✍️ Blog Post πŸ’» GitHub Repository Hey Reader πŸ‘‹πŸ½ this newsletter is about πŸ₯ AI πŸ€– We haven't talked too much about AI, Bedrock, MCPs, and agents yet - so we want to change that. Please let us know if this it interests you to build AI on AWS, or if you are much more interested on hands-on fundamentals services. Should we focus on AI Services? Yes, I want to learn to build...

Newsletter Header AWS FOR THE REAL WORLD ⏱️ Reading time: 8 minutes πŸŽ“ Main Learning: Migrating from Edgio to CloudFront ✍️ Blog Post πŸ’» GitHub Repository Hey Reader πŸ‘‹πŸ½ This newsletter edition is all about saving Lambda costs. I (Sandro is writing this one) was recently involved in saving Lambda costs for a client. So, I thought writing down my thought process was a good idea. Have fun with it! If you need help saving AWS costs or improving your infrastructure, just reply to this email! Now...

βŒ› Reading time: 8 minutes πŸŽ“ Main Learning: Federated Authentication with Cognito πŸ‘Ύ GitHub Repository ✍️ Read the Full Post Online πŸ”— Hey Reader πŸ‘‹πŸ½ Federated Authentication lets users sign in to your app using their existing accounts - most prominently Google! This approach eliminates the need to create and remember new credentials (which most users are very happy for! ✨), improving user experience and likely increasing conversion rates. πŸ“ˆ With OAuth 2.0 and Google as an identity provider, we...