Pulumi Crosswalk for AWS

Pulumi Crosswalk for AWS is a collection of libraries that use automatic well-architected best practices to make common infrastructure-as-code tasks in AWS easier and more secure.


Pulumi Crosswalk for AWS supports “day one” tasks, such as creating your initial container-based workloads using Amazon Elastic Container Service (ECS)—including Fargate or Kubernetes (EKS)—and creating serverless workloads using Amazon API Gateway and AWS Lambda. Secure and cost-conscious defaults are chosen so that simple programs automatically use best practices for the underlying infrastructure, enabling better productivity with confidence.

Pulumi Crosswalk for AWS also supports “day two and beyond” tasks, such as scaling your workload, securing and integrating it with your existing infrastructure, or going to production in multiple complex environments. This includes Amazon Virtual Private Cloud (VPC) for network isolation, AWS Auto Scaling for dynamic scaling, and AWS Identity and Access Management (IAM) for securing your infrastructure.

For example, this program builds and publishes a Dockerized application to a private Elastic Container Registry (ECR), spins up an ECS Fargate cluster, and runs a scalable, load balanced service, all in response to a single pulumi up command line invocation:

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

// Create a repository.
const repo = new awsx.ecr.Repository("my-repo");

// Build an image from the "./app" directory (relative to our project and containing Dockerfile),
// and publish it to our ECR repository provisioned above.
const image = new awsx.ecr.Image("image", {
    repositoryUrl: repo.url,
    path: "./app",

// Create an ECS Cluster
const cluster = new aws.ecs.Cluster("default-cluster");

// Create a load balancer on port 80 and spin up two instances of Nginx.
const lb = new awsx.lb.ApplicationLoadBalancer("nginx-lb");

const service = new awsx.ecs.FargateService("my-service", {
    cluster: cluster.arn,
    taskDefinitionArgs: {
        container: {
            image: image.imageUri,
            cpu: 512,
            memory: 128,
            essential: true,
            portMappings: [
                    containerPort: 80,
                    targetGroup: lb.defaultTargetGroup,

// Export the load balancer's address so that it's easy to access.
export const url = lb.loadBalancer.dnsName;
import pulumi
import pulumi_aws as aws
import pulumi_awsx as awsx

repo = awsx.ecr.Repository("my-repo");

image = awsx.ecr.Image("image",

cluster = aws.ecs.Cluster("default-cluster")

lb = awsx.lb.ApplicationLoadBalancer("nginx-lb")

service = awsx.ecs.FargateService("service",
                                          "nginx": awsx.ecs.TaskDefinitionContainerDefinitionArgs(

pulumi.export("url", lb.load_balancer.dns_name)
using System.Collections.Generic;
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Awsx.Ecs.Inputs;
using Aws = Pulumi.Aws;
using Ecr = Pulumi.Awsx.Ecr;
using Ecs = Pulumi.Awsx.Ecs;
using Lb = Pulumi.Awsx.Lb;

class MyStack : Stack
    public MyStack()
        var repo = new Ecr.Repository("my-repo");

        var image = new Ecr.Image("image", new Ecr.ImageArgs
            RepositoryUrl = repo.Url,
            Path = "./app",

        var cluster = new Aws.Ecs.Cluster("demo-cluster");

        var lb = new Lb.ApplicationLoadBalancer("nginx-lb");

        var service = new Ecs.FargateService("my-service", new Ecs.FargateServiceArgs
            Cluster = cluster.Arn,
            TaskDefinitionArgs = new FargateServiceTaskDefinitionArgs
                Container = new TaskDefinitionContainerDefinitionArgs
                    Memory = 128,
                    Cpu = 512,
                    Image = image.ImageUri,
                    Essential = true,
                    PortMappings = new TaskDefinitionPortMappingArgs
                        ContainerPort = 80,
                        TargetGroup = lb.DefaultTargetGroup,

class Program
    static Task<int> Main(string[] args) => Deployment.RunAsync<MyStack>();

This example uses the default VPC and reasonable security defaults, but supports easy customization of all aspects.

Getting Started

To get started with Pulumi Crosswalk for AWS, download and install Pulumi, and configure it to work with your AWS account. Afterwards, try the Getting Started tutorial or select one of the relevant User Guides to get started:




Core Infrastructure

Continuous Deployment

Other AWS Services

Pulumi supports the entirety of the AWS platform. If your favorite service isn’t listed above, check out:

Frequently Asked Questions (FAQ)

What Clouds Does Pulumi Crosswalk Support?

Pulumi Crosswalk supports AWS only at the moment. Support for additional clouds is on the roadmap (Azure, GCP, and Kubernetes).

What Languages are Supported?

Pulumi Crosswalk for AWS is available for all supported Pulumi languages.

What Packages Define Pulumi Crosswalk for AWS?

Because Pulumi Crosswalk for AWS is a broader “brand” for our framework spanning multiple packages, there isn’t a single package that contains everything. The @pulumi/aws, @pulumi/awsx, and @pulumi/eks packages each has an important role to play.

Is Pulumi Crosswalk for AWS Free to Use?

Yes, Pulumi Crosswalk for AWS is completely open source and free to use, along with the Individual Edition of Pulumi. Pulumi’s commercial offerings already fully support Pulumi Crosswalk for AWS.

If you would like to contribute to the packages, please see the relevant repo on GitHub: pulumi/pulumi-aws, pulumi/pulumi-awsx, or pulumi/eks. Issues and Pull Requests are welcome!

If I’m an Existing User, What Has Changed?

The primary change is new functionality added to the above packages, and the availability of these User Guides. Pulumi Crosswalk for AWS continues to work with the standard Pulumi CLI and Pulumi Service. If you already use the free Individual Edition, or paid Team or Enterprise Edition, you can continue to do so now with Pulumi Crosswalk for AWS functionality.

Upgrading from an old version of Pulumi Crosswalk for AWS?

Previous versions of @pulumi/awsx were TypeScript-only. The functionality has changed from these TypeScript-only versions. We have taken the opportunity to move the existing TypeScript-only functionality into a classic namespace. To create a VPC using the old TypeScript version of Crosswalk for AWS, the following code would work:

import * as awsx from "@pulumi/awsx/classic";

const vpc = new awsx.ec2.Vpc("classic-vpc", {});

Any resource that you use from the existing library can continue to be used from that classic namespace. All of the classic functionality is available in that namesoace.

Is Support or Training Available for Pulumi Crosswalk for AWS?

Yes! Please fill out this form and a Pulumi team member will be in touch.