meta_desc: "Use AWS CDK constructs from within Pulumi, combining Pulumi and AWS CDK resources, and getting the performance and rich features of the Pulumi platform."
meta_image: aws-cdk-on-pulumi.png
authors:
- luke-hoban
tags:
- aws-cdk
---
One of our key goals with Pulumi’s Universal Infrastructure as Code platform is to offer access to the widest range of cloud infrastructure building blocks for use within your cloud engineering projects. Over the years, that has led us to support interoperating seamlessly with a variety of alternative infrastructure definition formats, like Helm, CloudFormation, Azure Resource Manager and Kubernetes YAML. Today we’re really excited to add support for AWS CDK constructs to the list!
The AWS Cloud Development Kit (CDK) offers a large collection of higher-level libraries (“constructs”) for working with the AWS platform, built by service teams at AWS and by the AWS CDK community. These libraries are available in the same set of general purpose programming languages that Pulumi supports, with the primary difference being that AWS CDK compiles infrastructure programs into CloudFormation. This dependence on CloudFormation limits AWS CDK to being deployed via the CloudFormation deployment service which can slow down deployments and introduce some developer productivity friction due to the impedance mismatch between the program you write and the YAML it gets transpiled into.
With the new [AWS CDK on Pulumi](https://github.com/pulumi/pulumi-cdk) project, available in public preview today, we are opening up the ability to use AWS CDK constructs from within a Pulumi deployment. For users already using AWS CDK, this provides Pulumi as a new option for orchestrating deployments in place of CloudFormation, offering improved deployment speed, integration with the full set of features of the Pulumi Cloud Engineering Platform (like [Policy as Code](/docs/using-pulumi/crossguard/), [Audit Logs](/docs/pulumi-cloud/audit-logs/), Secrets, and much more). And for Pulumi users, they are now able to leverage and benefit from the decades of experience AWS teams and the AWS CDK community have invested in designing well-architected infrastructure patterns through these constructs.
Even better, you can also now combine AWS CDK and Pulumi resources in a single Pulumi infrastructure as code project - passing outputs from Pulumi resources into AWS CDK constructs, and outputs from AWS CDK constructs into Pulumi resources. This allows you to work across the more than 80 cloud and SaaS providers that Pulumi offers access to, while still benefiting from high level libraries from the AWS CDK project, and without the hassles of a transpiler.
## Deploying AWS CDK Constructs with Pulumi
To deploy existing AWS CDK Constructs using Pulumi, simply do the following:
1. Create a class that derives from `pulumicdk.Stack` (which itself is derived from `awscdk.Stack`).
2. In the constructor, use any AWS CDK constructs from existing libraries such as [`aws-cdk-lib`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html)
3. Call `this.synth()` to finalize the stack and deploy its resources.
Constructing an instance of this `pulumicdk.Stack` from within your Pulumi program will then deploy all of the infrastructure defined by the CDK constructs in the Stack using Pulumi.
For example, the following program deploys two AWS CDK Constructs using Pulumi.
```ts
import * as fs from 'fs';
import * as events from 'aws-cdk-lib/aws-events';
import * as events_targets from 'aws-cdk-lib/aws-events-targets';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Duration } from 'aws-cdk-lib';
import * as pulumicdk from '@pulumi/cdk';
import { remapCloudControlResource } from './adapter';
+ └─ cdk:construct:LambdaStack teststack/teststack created
+ ├─ cdk:construct:Function teststack/teststack/lambda created
+ │ ├─ cdk:construct:Role teststack/teststack/lambda/ServiceRole created
+ │ │ └─ aws-native:iam:Role lambdaServiceRole494E4CA6 created
+ │ └─ aws-native:lambda:Function lambda8B5974B5 created
+ └─ cdk:construct:Rule teststack/teststack/rule created
+ ├─ aws:cloudwatch:EventRule ruleF2C1DCDC created
+ ├─ aws:cloudwatch:EventTarget Target0 created
+ └─ aws:lambda:Permission ruleAllowEventRuleteststacklambda47768855D6EFF36B created
Resources:
+ 11 created
Duration: 48s
```
We can see that each CDK Construct is shown in the Pulumi resource tree, and the leaf nodes of the deployment are the underlying AWS resources needed for this cloud infrastructure. Note that they are deployed via Pulumi, not via CloudFormation. This enables faster deployments, because Pulumi coordinates directly with AWS instead of going through CloudFormation, as well as the ability to use Pulumi features like `pulumi logs`, Policy as Code, and the features of the Pulumi Service.

## Using AWS CDK Constructs Within Pulumi Programs
We can also combine the best of AWS CDK with the best of Pulumi, by using both Pulumi resources and AWS CDK Constructs in the same deployment. This enables combining rich AWS CDK Constructs with the breadth of the Pulumi ecosystem, including support for multiple cloud and SaaS providers.
The following example shows creating an AWS Lambda Function with the Pulumi AWS SDK, and then using an output of that Function (the `arn`) as an input to an AWS Events Rule CDK Construct. An output from the AWS CDK Construct is then converted to a Pulumi Output value which can be used in the rest of the Pulumi program - and in particular as a Pulumi Stack Output.
```ts
import * as events from 'aws-cdk-lib/aws-events';
import * as events_targets from 'aws-cdk-lib/aws-events-targets';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as pulumi from '@pulumi/pulumi';
import * as pulumicdk from '@pulumi/cdk';
import * as aws from '@pulumi/aws';
import { remapCloudControlResource } from './adapter';
// Create a resource in Pulumi
const fn = new aws.lambda.CallbackFunction('lambda', {
Note how the `pulumicdk.asString` and `asOutput` functions are used to convert Pulumi [Outputs](/docs/concepts/inputs-outputs/) to AWS CDK [Tokens](https://docs.aws.amazon.com/cdk/v2/guide/tokens.html) and vice-versa to map values out of and into Pulumi.
Last year we released a new [AWS Native](/blog/announcing-aws-native/) Pulumi provider in preview. The AWS Native provider builds on the new [AWS Cloud Control API](https://aws.amazon.com/blogs/aws/announcing-aws-cloud-control-api/), which offers direct provisioning support for the same resource model supported by AWS CloudFormation.
The new AWS CDK on Pulumi builds upon AWS Native by converting the CloudFormation resource tree into the corresponding resource definitions from the AWS Native provider. This provides a high fidelity mapping of each resource into Pulumi. The coverage provided by AWS Cloud Control API (and thus AWS Native) is not yet complete across the entire breadth of the CloudFormation resource model though, so for some resources, it may be necessary to map them to a resource definition to use via the AWS Classic provider. This is handled via the `remapCloudControlResource` API which allows providing a custom mapping for a given CloudFormation resource type which is not yet supported in Pulumi AWS Native and AWS Cloud Control.
For example, to provide a mapping for the `AWS::Lambda::Permission` resource type, define a function like the following:
In many cases, this is not needed, as AWS CDK on Pulumi offers builtin support for remapping many common resources. Over the coming months, as AWS Cloud Control API support expands to cover more of the CloudFormation resource model, these remappings will become less necessary in practice, with almost all resources being supported directly via Pulumi AWS Native.
## Using High-Level "L3" Constructs
AWS CDK offers a mix of relatively low level (unopinionated) constructs, as well as high level (more opinionated) constructs. With AWS CDK on Pulumi, we can use any of these. This includes libraries like [`aws-ecs-patterns`](https://docs.aws.amazon.com/cdk/api/v1/docs/aws-ecs-patterns-readme.html) and [AWS Solutions Constructs](https://aws.amazon.com/solutions/constructs/patterns/).
For example, to deploy a load balanced and auto-scaled Fargate service to a dedicated VPC, we can use the following program:
```ts
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as pulumi from '@pulumi/pulumi';
import * as pulumicdk from '@pulumi/cdk';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns';
import { Construct } from 'constructs';
import { Stack, Duration, CfnOutput } from 'aws-cdk-lib';
import {remapCloudControlResource } from './adapter';
Deploying this with `pulumi up` builds a few dozen AWS resources to construct the various building blocks necessary to capture this in raw AWS infrastructure:
Currently AWS CDK on Pulumi is supported only for TypeScript users, due to how the AWS CDK synthesis process (implemented in TypeScript) must be invoked from within the Pulumi program. We are exploring ways to bring this support into other Pulumi (and CDK) languages as part of future updates to the library.
In the meantime, AWS CDK on Pulumi can be used within Component Packages implemented in TypeScript, and exposed to any Pulumi language (including newly supported [Java](/blog/announcing-infrastructure-as-code-with-java-and-pulumi/) and [YAML](/blog/pulumi-yaml/).
Support for deploying AWS CDK constructs from within Pulumi programs opens up a wide range of new opportunities to interoperate between the AWS CDK and Pulumi ecosystems.For existing AWS CDK users, this provides new ways to deploy your CDK infrastructure and constructs. For existing Pulumi users, this opens up new higher-level libraries from the AWS CDK to use from within your Pulumi programs. We’re excited to be bringing these two communities closer together, and can’t wait to see what cloud builders can do with these two great cloud technologies together.
The AWS CDK on Pulumi project is open source at [https://github.com/pulumi/pulumi-cdk](https://github.com/pulumi/pulumi-cdk) and on NPM at [https://www.npmjs.com/package/@pulumi/cdk](https://www.npmjs.com/package/@pulumi/cdk). Get started today!