Pulumi for Terraform Users

The open source infrastructure as code platform

Pulumi is fully open source while Terraform is committed to the Business Source License, a restrictive source available license. Pulumi uses general purpose programming languages and YAML that better help you tame cloud complexity and accelerate development velocity, rather than proprietary domain-specific languages (DSL) such as HashiCorp Configuration Language (HCL). See our Pulumi vs. Terraform guide for detailed differences between the two platforms.

Migrate off of Terraform to a more modern and open source infrastructure as code platform.

The benefits of using Pulumi

Committed to open source

Pulumi is fully open source and is Apache 2.0 licensed. It does not and never will depend on Business Source License software in any way.

Tame cloud complexity

Deliver infrastructure from 100+ cloud and SaaS providers. Pulumi’s SDKs provide a complete and consistent interface that offers full access to clouds and abstracts complexity.

Bring the cloud closer to application development

Build reusable cloud infrastructure and infrastructure platforms that empower developers to build modern cloud applications faster and with less overhead.

Use engineering practices with infrastructure

Use engineering practices with infrastructure to replace inefficient, manual infrastructure processes with automation. Test and deliver infrastructure through CI/CD workflows or automate deployments with code at runtime.

Take advantage of real coding features with Pulumi

Pulumi provides a more expressive and efficient way to define cloud resources:

  • Use variable loops, not copy/paste
  • Use any Node libaries (or Python/Go)
  • On-the-fly error checking
  • Freeform code instead of complex interpolations

Find many other examples here.

import * as aws from "@pulumi/aws";
import { readdirSync } from "fs";
import { join as pathjoin } from "path";

const bucket = new aws.s3.Bucket("mybucket");
const folder = "./files";
let files = readdirSync(folder);

for (let file of files) {
    const object = new aws.s3.BucketObject(file, {
        bucket: bucket,
        source: new pulumi.FileAsset(pathjoin(folder, file))

export const bucketname = bucket.id;
resource "aws_s3_bucket" "mybucket" {
    bucket_prefix = "mybucket"

resource "aws_s3_bucket_object" "data_txt" {
    key        = "data.txt"
    bucket     = "${aws_s3_bucket.mybucket.id}"
    source     = "./files/data.txt"

resource "aws_s3_bucket_object" "index_html" {
    key        = "index.html"
    bucket     = "${aws_s3_bucket.mybucket.id}"
    source     = "./files/index.html"

resource "aws_s3_bucket_object" "index_js" {
    key        = "index.js"
    bucket     = "${aws_s3_bucket.mybucket.id}"
    source     = "./files/index.js"

resource "aws_s3_bucket_object" "main.css" {
    key        = "main.css"
    bucket     = "${aws_s3_bucket.mybucket.id}"
    source     = "./files/main.css"

resource "aws_s3_bucket_object" "favicon.ico" {
    key        = "favicon.ico"
    bucket     = "${aws_s3_bucket.mybucket.id}"
    source     = "./files/favicon.ico"

Productive cloud native programming

Pulumi is designed with cloud native computing in mind - from containers to serverless, providing a productive model for quickly building and deploying apps:

  • Rich, built in support for event handlers
  • Easy-to-use in-line Lambdas for simple functions
  • Use JavaScript for both infrastructure and Lambda callbacks
  • Avoid the need for significant boiler plate code

Find many other examples here.

import * as aws from "@pulumi/aws";

// Create an S3 Bucket.
const bucket = new aws.s3.Bucket("mybucket");

// Register a Lambda to handle the Bucket notification.
bucket.onObjectCreated("newObj", async (ev, ctx) => {
    // Write code inline, or use a Zip

// Export the bucket name for easy scripting.
export const bucketName = bucket.id;
resource "aws_s3_bucket" "mybucket" {
    bucket_prefix = "mybucket"

data "archive_file" "lambda_zip" {
    type        = "zip"
    output_path = "lambda.zip"

    source {
        filename = "index.js"
        content = < {

data "aws_iam_policy_document" "lambda-assume-role-policy" {
    statement {
        actions = ["sts:AssumeRole"]

        principals {
            type        = "Service"
            identifiers = ["lambda.amazonaws.com"]

resource "aws_iam_role" "lambda" {
    assume_role_policy = "${data.aws_iam_policy_document.lambda-assume-role-policy.json}"

resource "aws_lambda_function" "my_lambda" {
    filename = "${data.archive_file.lambda_zip.output_path}"
    source_code_hash = "${data.archive_file.lambda_zip.output_base64sha256}"
    function_name = "my_lambda"
    role = "${aws_iam_role.lambda.arn}"
    handler = "index.handler"
    runtime = "nodejs8.10"

resource "aws_lambda_permission" "allow_bucket" {
    statement_id  = "AllowExecutionFromS3Bucket"
    action        = "lambda:InvokeFunction"
    function_name = "${aws_lambda_function.my_lambda.arn}"
    principal     = "s3.amazonaws.com"
    source_arn    = "${aws_s3_bucket.mybucket.arn}"

resource "aws_s3_bucket_notification" "bucket_notification" {
    bucket = "${aws_s3_bucket.mybucket.id}"

    lambda_function {
        lambda_function_arn = "${aws_lambda_function.my_lambda.arn}"
        events              = ["s3:ObjectCreated:*"]

output "bucket_name" {
    value = "${aws_s3_bucket.mybucket.id}"

Next Steps with Pulumi

Follow our Get Started guide to begin using Pulumi. If you need help migrating from Terraform, our Expert Services team can help migrate your Terraform workspaces and train your team. Talk to a Pulumi team member to get started.