aws-cdk-lib review
Our aws-cdk-lib 2.266.0 install occupied 174 MB, which makes sense once you see what is inside: one package contains CDK v2 constructs for AWS services, the core App and Stack model, CloudFormation-level L1 classes, higher-level L2 and L3 abstractions, and assertion helpers. TypeScript or JavaScript code builds a construct tree, then the separate aws-cdk CLI synthesizes that tree into CloudFormation and deploys it. Version 2.266.0 adds EKS control-plane scaling configuration, refreshes generated CloudFormation definitions, and fixes EC2 IPv6 route dependencies plus SNS-to-SQS principals in opt-in regions.
aws-cdk-lib 2.266.0 installed in 6.9 seconds but occupied 174 MB in our sandbox, so it earns its place only when AWS-aware constructs save more work than the package and CloudFormation machinery add. It is a strong fit for TypeScript teams committed to AWS, provided every change is reviewed through the synthesized template and diff.
We installed it
| Install | ✓ · 6.9s | 5 packages on disk · 174 MB |
| Import | ✓ | ESM import works · require() works · CommonJS package with exports map |
| Browser | n/a | could not be bundled for the browser (Node-only code, most likely) |
| Types | ✓ | TypeScript types bundled |
| Known vulns | 0 | 0 critical · 0 high · 0 moderate · 0 low (npm audit) |
Answers from our run
Does aws-cdk-lib install cleanly?
Yes. In a fresh container with an empty cache, npm install aws-cdk-lib finished in 7 seconds, leaving 5 packages and 174 MB on disk. npm audit reported no known vulnerabilities.
Can aws-cdk-lib run in a browser?
Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.
Does aws-cdk-lib work with both ESM and CommonJS?
Yes. Both import 'aws-cdk-lib' and require('aws-cdk-lib') worked in Node 22 in our run. The package is published as CommonJS with an exports map.
Does aws-cdk-lib include TypeScript types?
Yes, type declarations ship inside the package, so no @types install is needed.
aws-cdk-lib or @pulumi/aws: which should you use?
@pulumi/aws: Choose it when TypeScript is preferred but Pulumi state and a multi-cloud programming model fit the platform better. aws-cdk-lib 2.266.0 installed in 6.9 seconds but occupied 174 MB in our sandbox, so it earns its place only when AWS-aware constructs save more work than the package and CloudFormation machinery add.
When should you not use aws-cdk-lib?
Your platform spans AWS, Azure, and Google Cloud under one state model. This package emits AWS CloudFormation, so Pulumi or CDK for Terraform is a closer architectural match.
Use it if
- Your team deploys mainly to AWS and wants CloudFormation to remain the system that creates, updates, and deletes resources.
- You want infrastructure definitions to use TypeScript functions, loops, tests, and reusable Construct classes.
- Service-aware helpers such as grantReadWriteData and Lambda event integrations save enough IAM and wiring work to justify generated templates.
- You need both high-level constructs and direct L1 access when a new CloudFormation property has not reached an L2 construct yet.
- Your platform spans AWS, Azure, and Google Cloud under one state model. This package emits AWS CloudFormation, so Pulumi or CDK for Terraform is a closer architectural match.
- A 174 MB install is unreasonable for the repository or build image. Our clean install left 5 packages, while the package itself was 151776 KB unpacked.
- Reviewers need handwritten declarative resources with few generated surprises. An L2 construct can add IAM policies, roles, custom resources, assets, or defaults that only become obvious in cdk synth and cdk diff output.
- You plan to adopt alpha modules while requiring strict semantic-version compatibility. The repository states that stable modules follow semver, but experimental modules may introduce breaking changes in any release.
- The target cannot run Node-only tooling or provision AWS bootstrap resources. Our browser bundle failed, and deployment normally relies on credentials, CloudFormation roles, an asset bucket, and an ECR repository created by cdk bootstrap.
Setup reality
We installed aws-cdk-lib 2.266.0 in a fresh Node 22 Bookworm container. npm finished in 6.9 seconds, left 5 packages, and used 174 MB on disk. The package declares 15 direct dependencies plus the constructs peer, and its unpacked size is 151776 KB. npm audit reported 0 known vulnerabilities. Bundled TypeScript declarations were present, and both require() and ESM import worked through the CommonJS package and exports map. An esbuild browser bundle failed because this is Node-oriented infrastructure code.
Install constructs alongside the library, and keep the aws-cdk CLI as a separate development dependency. Node 20 is the minimum. A CDK app needs an entry command in cdk.json; TypeScript projects also need their compiler and runner setup. Version the CLI in the repository so local work and CI synthesize with the same tool instead of whatever happens to be installed globally.
AWS access starts to matter before deploy when a construct performs a context lookup. Calls such as Vpc.fromLookup query the target account and cache the answer in cdk.context.json. Commit that file when repeatable synthesis matters. Environment-specific stacks need an account and region, commonly from CDK_DEFAULT_ACCOUNT and CDK_DEFAULT_REGION. Each account and region usually needs cdk bootstrap once before assets can be published or deployment roles assumed.
Treat cdk synth and cdk diff as review inputs, not ceremony. A short construct can produce many CloudFormation resources, and updates may replace stateful infrastructure. Lambda archives, Docker images, and other assets add staging and upload work; some constructs invoke Docker or an external bundler locally. RemovalPolicy.RETAIN protects data from stack deletion but leaves resources and charges behind for manual cleanup.
Patterns
Pin the construct library and CLI install-cdk-v2
npm install aws-cdk-lib@2.266.0 constructs@^10.5.0
npm install --save-dev aws-cdk@^2aws-cdk-lib contains constructs; the aws-cdk development dependency supplies bootstrap, synth, diff, and deploy commands.
Create an account-specific stack define-app-stack
import { App, Stack } from 'aws-cdk-lib';
const app = new App();
const stack = new Stack(app, 'OrdersStack', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});
app.synth();An explicit account and region allow context lookups, but the resulting assembly is tied to that AWS environment.
Keep an S3 bucket after stack deletion create-retained-bucket
import { RemovalPolicy } from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
const bucket = new s3.Bucket(stack, 'Documents', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED,
enforceSSL: true,
versioned: true,
removalPolicy: RemovalPolicy.RETAIN,
});RETAIN prevents CloudFormation from deleting the bucket with the stack. You remain responsible for its data and charges.
Stage a directory for Lambda package-lambda-asset
import * as lambda from 'aws-cdk-lib/aws-lambda';
const handler = new lambda.Function(stack, 'Handler', {
runtime: lambda.Runtime.NODEJS_22_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda'),
});Code.fromAsset uploads the directory as a deployment asset. Compile source first and exclude files the function does not need.
Connect API Gateway to Lambda create-http-endpoint
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
const api = new apigateway.LambdaRestApi(stack, 'OrdersApi', {
handler,
proxy: false,
});
api.root.addResource('orders').addMethod('GET');proxy: false requires explicit resources and methods. CDK also adds permission for API Gateway to invoke the function.
Create a retained on-demand table create-dynamodb-table
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
const table = new dynamodb.Table(stack, 'Orders', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: true },
removalPolicy: RemovalPolicy.RETAIN,
});DynamoDB key-schema changes commonly require replacement. RETAIN keeps the old table if the stack is removed.
Give a function table permissions grant-table-access
table.grantReadWriteData(handler);
handler.addEnvironment('TABLE_NAME', table.tableName);grantReadWriteData adds resource-scoped IAM actions to the function role; inspect cdk diff to see the exact policy change.
Import a bucket by name reference-existing-bucket
const logs = s3.Bucket.fromBucketName(
stack,
'ExistingLogs',
'company-central-logs',
);
logs.grantRead(handler);The imported construct is a reference. CloudFormation does not gain ownership of the existing bucket.
Resolve a VPC during synthesis lookup-vpc
import * as ec2 from 'aws-cdk-lib/aws-ec2';
const vpc = ec2.Vpc.fromLookup(stack, 'Vpc', {
tags: { Environment: 'production' },
});fromLookup needs AWS credentials and an environment-specific stack. CDK stores the resolved value in cdk.context.json.
Expose a non-secret endpoint publish-stack-output
import { CfnOutput } from 'aws-cdk-lib';
new CfnOutput(stack, 'ApiUrl', {
value: api.url,
description: 'Orders API base URL',
});CloudFormation outputs are visible to users who can inspect the stack. Do not put credentials or secret values here.
Tag supported descendants apply-resource-tags
import { Tags } from 'aws-cdk-lib';
Tags.of(stack).add('Environment', 'production');
Tags.of(stack).add('Owner', 'platform');Tags flow through the construct tree only where the target AWS resource supports the relevant tag behavior.
Assert on CloudFormation output test-synthesized-template
import { App } from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
const app = new App();
const testStack = new OrdersStack(app, 'TestStack');
const template = Template.fromStack(testStack);
template.hasResourceProperties('AWS::S3::Bucket', {
VersioningConfiguration: { Status: 'Enabled' },
});Template assertions detect changes in synthesized resources, including defaults introduced by higher-level constructs.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| @pulumi/aws | npm | Choose it when TypeScript is preferred but Pulumi state and a multi-cloud programming model fit the platform better. |
| cdktf | npm | Choose it when Terraform providers, plans, and state are requirements while constructs remain the desired authoring model. |
| sst | npm | Choose it for an opinionated application workflow around AWS functions and web frontends rather than direct use of the full CDK construct catalogue. |
More infra guides
boto3 · opentelemetry-api · psutil · distro · @opentelemetry/api · google-cloud-storage · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

