AWS CDK vs Pulumi: A detailed comparison

Infrastructure as a service, often called “the cloud,” is the status quo for modern software companies. But while it’s a great relief not to own infrastructure anymore, you still have to manage it yourself.

The most prevalent way to do so is by writing YAML or JSON files for provisioning in different environments. Tools like Terraform and CloudFormation are the most prominent here, but they aren’t without issues; they started with simple markup languages that didn’t allow for logic but then grew, adding new general programming language features over time. Each tool had a custom programming language that used YAML or JSON but had many concepts hidden behind its markup facade.

That’s why a new generation of tools has emerged in recent years. These accept the requirement of full-fledged programming concepts in their configuration language right from the start. They also use general programming languages instead of markup as their configuration language. Best of all, they don’t just choose one language and force it on you; each tool offers several general programming languages to implement your infrastructure.

This means chances are good that one of these tools will offer a programming language you already know, so you don’t have to learn new syntax just to add infrastructure to your applications. In addition, all the language tools you know work with IaC tools so that you can operate in a familiar environment.

The two most prominent tools on the market right now are Pulumi and AWS CDK. This article will look at each of these to discuss how they differ and when to use which.

Supported programming languages

As mentioned above, Pulumi and AWS CDK support a wide array of programming languages. This means you have a choice as to how to code your infrastructure. While they have significant overlap in supported languages, they differ a bit.

Both Pulumi and AWS CDK support JavaScript, TypeScript, Python, .Net, and Java. If you want to use one of these languages, you don’t have to decide which tool to use.

Pulumi additionally supports Go and YAML. If you want to leverage your Go skills, Pulumi might be your only option. YAML support might seem strange, but it's a good option for simple deployments. Why use a heavy-weight programming language if you have a simple deployment?

Supported cloud providers

Pulumi has a vast registry of cloud providers it supports, making it the multi-cloud tool of choice. It’s charming if you favor small providers with specific services that don’t make much sense to use on their own. For some services, Pulumi uses Terraform in the background, which means providers with Terraform support usually work with Pulumi.

AWS CDK, on the other hand, is AWS-specific. It’s created by AWS and optimized for their infrastructure requirements. If you only use AWS, you will probably have smooth sailing with its CDK.

AWS also noticed the power of their new tool and opened it to the public. This means many community projects have cropped up that support infrastructure unrelated to AWS. Terraform CDK and CDK8s are notable projects here. So, while you can’t use AWS CDK for Azure, the Terraform-based fork might be an option here.

Cloud provider integrations

Pulumi and AWS CDK follow different approaches to integrating with their respective providers.

Pulumi tries to use the native AWS Cloud Control API to provision its infrastructure. This means Pulumi sends commands to the provisioning API of a cloud provider. These APIs also help with service discovery, so the tools using them don’t need to write integrations from scratch when new services are released.

If a provider doesn’t offer a cloud control API, Pulumi can fall back on Terraform and even allows you to implement an integration yourself.

AWS CDK is more of an abstraction over CloudFormation. It will generate JSON files that it sends to CloudFormation for deployment. This means that while you get all the CloudFormation features out of the box, you also have to wait for CloudFormation support before you can use a service with CDK. But it also supports and even encourages writing custom integrations for your services. If AWS doesn’t see CloudFormation support as necessary, you can still implement it yourself or possibly get a community-supported integration from NPM.

Example application

On GitHub, you can find an example application consisting of an S3 bucket for website hosting, a Lambda function, and an API Gateway.

The repository has four directories.

  • A cdk directory that defines the infrastructure with AWS CDK
  • A pulumi directory that defines the infrastructure with Pulumi
  • A function directory that contains the JavaScript code for the Lambda function, which will handle API requests
  • A website directory with the HTML code for the website that will be hosted in the S3 bucket

The Pulumi implementation

You can find the infrastructure definition of the Pulumi version in pulumi/index.ts. It’s written in TypeScript and quite explicit regarding resource definitions.

For example, it requires us to define the IAM role for the Lambda function manually before defining the function:

const role = new aws.iam.Role("role", { 
assumeRolePolicy: {
Version: "2012-10-17",
Statement: [
{
Action: "sts:AssumeRole",
Principal: { Service: "lambda.amazonaws.com" },
Effect: "Allow",
Sid: "",
},
],
},
});

new aws.iam.RolePolicyAttachment("roleAttachment", {
role,
policyArn: aws.iam.ManagedPolicy.AWSLambdaBasicExecutionRole,
});

const lambda = new aws.lambda.Function("lambda", {
role: role.arn,
runtime: "nodejs16.x",
handler: "index.handler",
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("../function"),
}),
});

We also have to manually define the Lambda integration, route, and stage of our API, which makes the whole process quite cumbersome:

const gateway = new aws.apigatewayv2.Api("gateway", { 
protocolType: "HTTP"
});

new aws.lambda.Permission(
"permission",
{
action: "lambda:InvokeFunction",
principal: "apigateway.amazonaws.com",
function: lambda,
sourceArn: pulumi.interpolate`${gateway.executionArn}/*/*`,
},
{ dependsOn: [gateway, lambda] }
);

const integration = new
aws.apigatewayv2.Integration("integration", {
apiId: gateway.id,
integrationType: "AWS_PROXY",
integrationUri: lambda.arn,
integrationMethod: "POST",
payloadFormatVersion: "2.0",
passthroughBehavior: "WHEN_NO_MATCH",
});

const route = new aws.apigatewayv2.Route("route", {
apiId: gateway.id,
routeKey: "$default",
target: pulumi.interpolate`integrations/${integration.id}`,
});

const stage = new aws.apigatewayv2.Stage(
"stage",
{
apiId: gateway.id,
name: pulumi.getStack(),
routeSettings: [{ routeKey: route.routeKey }],
autoDeploy: true,
},
{ dependsOn: [route] }
);

With Pulumi Crosswalk for AWS, an additional library, some of this extra work should go away, but out of the box, Pulumi is a bit more chatty than AWS CDK.

AWS CDK implementation

You can find the CDK implementation in cdk/lib/cdk-stack.ts. It is also written in TypeScript, but is much terser than the Pulumi version.

Defining an API gateway that handles requests with a Lambda function takes less than 10 lines of code:

const gateway = new apigw.LambdaRestApi(this, "gateway", { 
handler: new lambda.Function(this, "function", {
runtime: lambda.Runtime.NODEJS_16_X,
handler: "index.handler",
code: lambda.Code.fromAsset(path.join(__dirname, "../../function")),
}),
});

This makes AWS CDK a quicker solution when you are only working with AWS.

Summary

Pulumi and AWS CDK are potent tools, each with its own strengths and weaknesses.

If you only use AWS services, then AWS CDK is the way to go; it has highly optimized constructs that allow you to define your infrastructure with much less code than Pulumi.

Pulumi is multicolored right from the start; it is suitable for putting together multiple small cloud providers with services that work well but aren't as fully fledged as AWS. It also comes with Go support, so if your infrastructure teams favor this language, Pulumi might be a better choice.

Was this article helpful?
Monitor your AWS environment

AWS Monitoring helps you gain observability into your AWS environment

Related Articles

Write For Us

Write for Site24x7 is a special writing program that supports writers who create content for Site24x7 "Learn" portal. Get paid for your writing.

Write For Us

Write for Site24x7 is a special writing program that supports writers who create content for Site24x7 “Learn” portal. Get paid for your writing.

Apply Now
Write For Us