AWS CDK TypeScript Overview Use this skill to build AWS infrastructure in TypeScript with reusable constructs, safe defaults, and a validation-first delivery loop. When to Use Use this skill when: - Creating or refactoring a CDK app, stack, or reusable construct in TypeScript - Choosing between L1, L2, and L3 constructs - Building serverless, networking, or security-focused AWS infrastructure - Wiring multi-stack applications and environment-aware deployments - Validating infrastructure changes with , tests, , and Instructions 1. Project Initialization 2. Core Architecture 3. Construct Levels…

: 'ts-jest' },\n};\n```\n\n---\n\n## Fine-Grained Assertions\n\n### Basic Resource Assertions\n\n```typescript\nimport { App } from 'aws-cdk-lib';\nimport { Template, Match } from 'aws-cdk-lib/assertions';\nimport { MyStack } from '../lib/my-stack';\n\ndescribe('MyStack', () => {\n let template: Template;\n\n beforeEach(() => {\n const app = new App();\n const stack = new MyStack(app, 'TestStack');\n template = Template.fromStack(stack);\n });\n\n test('creates a DynamoDB table with PAY_PER_REQUEST', () => {\n template.hasResourceProperties('AWS::DynamoDB::Table', {\n BillingMode: 'PAY_PER_REQUEST',\n });\n });\n\n test('creates a Lambda function with correct runtime', () => {\n template.hasResourceProperties('AWS::Lambda::Function', {\n Runtime: 'nodejs20.x',\n Timeout: 30,\n });\n });\n\n test('creates exactly 2 Lambda functions', () => {\n template.resourceCountIs('AWS::Lambda::Function', 2);\n });\n});\n```\n\n### Match Helpers\n\n```typescript\nimport { Match } from 'aws-cdk-lib/assertions';\n\n// Match any value\ntemplate.hasResourceProperties('AWS::Lambda::Function', {\n Handler: Match.anyValue(),\n Runtime: 'nodejs20.x',\n});\n\n// Match object with specific keys (ignoring others)\ntemplate.hasResourceProperties('AWS::Lambda::Function', {\n Environment: {\n Variables: Match.objectLike({\n TABLE_NAME: Match.anyValue(),\n }),\n },\n});\n\n// Match absent property\ntemplate.hasResourceProperties('AWS::S3::Bucket', {\n PublicAccessBlockConfiguration: {\n BlockPublicAcls: true,\n },\n WebsiteConfiguration: Match.absent(),\n});\n\n// Match array containing specific elements\ntemplate.hasResourceProperties('AWS::IAM::Role', {\n ManagedPolicyArns: Match.arrayWith([\n Match.objectLike({\n 'Fn::Join': Match.anyValue(),\n }),\n ]),\n});\n```\n\n### Testing Resource Counts\n\n```typescript\ntest('creates expected number of resources', () => {\n template.resourceCountIs('AWS::Lambda::Function', 3);\n template.resourceCountIs('AWS::DynamoDB::Table', 1);\n template.resourceCountIs('AWS::SQS::Queue', 2); // main + DLQ\n template.resourceCountIs('AWS::ApiGateway::RestApi', 1);\n});\n```\n\n### Testing Outputs\n\n```typescript\ntest('exports API URL', () => {\n template.hasOutput('ApiUrl', {\n Value: Match.anyValue(),\n });\n});\n```\n\n---\n\n## Snapshot Testing\n\nSnapshot tests capture the entire synthesized template and detect any change.\n\n### Basic Snapshot\n\n```typescript\ntest('matches snapshot', () => {\n const app = new App();\n const stack = new MyStack(app, 'TestStack');\n const template = Template.fromStack(stack);\n\n expect(template.toJSON()).toMatchSnapshot();\n});\n```\n\n### Updating Snapshots\n\n```bash\n# Regenerate snapshots after intentional changes\nnpx jest --updateSnapshot\n```\n\n### When to Use Snapshots\n\n| Scenario | Recommended |\n|----------|-------------|\n| Detect accidental changes | ✅ Yes |\n| Verify specific properties | ❌ Use fine-grained assertions |\n| Stable, rarely-changing stacks | ✅ Yes |\n| Rapidly iterating stacks | ❌ Too many snapshot updates |\n\n---\n\n## Validation Testing\n\nTest custom validation logic in your constructs.\n\n```typescript\nimport { App, Stack } from 'aws-cdk-lib';\n\n// Custom construct with validation\nclass MyConstruct extends Construct {\n constructor(scope: Construct, id: string, props: { maxRetries: number }) {\n super(scope, id);\n if (props.maxRetries \u003c 0 || props.maxRetries > 10) {\n throw new Error('maxRetries must be between 0 and 10');\n }\n }\n}\n\n// Test validation\ntest('throws on invalid maxRetries', () => {\n const app = new App();\n const stack = new Stack(app, 'TestStack');\n\n expect(() => {\n new MyConstruct(stack, 'Bad', { maxRetries: -1 });\n }).toThrow('maxRetries must be between 0 and 10');\n\n expect(() => {\n new MyConstruct(stack, 'Also Bad', { maxRetries: 99 });\n }).toThrow('maxRetries must be between 0 and 10');\n});\n\ntest('accepts valid maxRetries', () => {\n const app = new App();\n const stack = new Stack(app, 'TestStack');\n\n expect(() => {\n new MyConstruct(stack, 'Good', { maxRetries: 3 });\n }).not.toThrow();\n});\n```\n\n---\n\n## Integration Testing\n\n### CDK integ-tests Module\n\n```typescript\nimport { IntegTest } from '@aws-cdk/integ-tests-alpha';\nimport { App } from 'aws-cdk-lib';\n\nconst app = new App();\nconst stack = new MyStack(app, 'IntegTestStack');\n\nconst integ = new IntegTest(app, 'MyIntegTest', {\n testCases: [stack],\n diffAssets: true,\n stackUpdateWorkflow: true,\n});\n\n// Assert deployed resources\ninteg.assertions\n .httpApiCall('https://my-api.execute-api.us-east-1.amazonaws.com/items')\n .expect(ExpectedResult.objectLike({ statusCode: 200 }));\n```\n\n### Running Integration Tests\n\n```bash\n# Deploy and test\nnpx integ-runner --directory test/integ --parallel-regions us-east-1\n\n# Update snapshots after successful deploy\nnpx integ-runner --directory test/integ --update-on-failed\n```\n\n---\n\n## CDK Nag Compliance\n\nCDK Nag checks your stacks against best-practice rule packs.\n\n### Setup\n\n```bash\nnpm install cdk-nag\n```\n\n```typescript\nimport { Aspects } from 'aws-cdk-lib';\nimport { AwsSolutionsChecks, HIPAASecurityChecks } from 'cdk-nag';\n\nconst app = new App();\nconst stack = new MyStack(app, 'ProdStack');\n\n// Add compliance checks\nAspects.of(stack).add(new AwsSolutionsChecks({ verbose: true }));\n// Or HIPAA compliance\n// Aspects.of(stack).add(new HIPAASecurityChecks());\n```\n\n### Available Rule Packs\n\n| Pack | Description |\n|------|-------------|\n| `AwsSolutionsChecks` | AWS Solutions Library best practices |\n| `HIPAASecurityChecks` | HIPAA compliance rules |\n| `NIST80053R4Checks` | NIST 800-53 Rev 4 |\n| `NIST80053R5Checks` | NIST 800-53 Rev 5 |\n| `PCI321Checks` | PCI DSS 3.2.1 |\n\n### Suppressing Rules\n\n```typescript\nimport { NagSuppressions } from 'cdk-nag';\n\n// Suppress at resource level\nNagSuppressions.addResourceSuppressions(myBucket, [\n { id: 'AwsSolutions-S1', reason: 'Access logging not needed for dev' },\n]);\n\n// Suppress at stack level\nNagSuppressions.addStackSuppressions(stack, [\n { id: 'AwsSolutions-IAM4', reason: 'Using AWS managed policies is acceptable here' },\n]);\n```\n\n### Testing with CDK Nag\n\n```typescript\nimport { Annotations } from 'aws-cdk-lib/assertions';\nimport { AwsSolutionsChecks } from 'cdk-nag';\n\ntest('passes AWS Solutions checks', () => {\n const app = new App();\n const stack = new MyStack(app, 'TestStack');\n Aspects.of(stack).add(new AwsSolutionsChecks());\n\n const annotations = Annotations.fromStack(stack);\n\n // No errors\n annotations.hasNoError('*', Match.anyValue());\n\n // Optionally check no warnings\n annotations.hasNoWarning('*', Match.anyValue());\n});\n```\n\n---\n\n## Testing Patterns\n\n### Pattern: Test Environment-Specific Behavior\n\n```typescript\ntest('production stack has termination protection', () => {\n const app = new App();\n const stack = new MyStack(app, 'ProdStack', {\n env: { account: '123456789012', region: 'us-east-1' },\n terminationProtection: true,\n });\n\n expect(stack.terminationProtection).toBe(true);\n});\n\ntest('dev stack allows removal', () => {\n const app = new App();\n const stack = new MyStack(app, 'DevStack', {\n terminationProtection: false,\n });\n const template = Template.fromStack(stack);\n\n template.hasResource('AWS::DynamoDB::Table', {\n DeletionPolicy: 'Delete',\n });\n});\n```\n\n### Pattern: Test IAM Permissions\n\n```typescript\ntest('Lambda has read-only access to S3', () => {\n const template = Template.fromStack(stack);\n\n template.hasResourceProperties('AWS::IAM::Policy', {\n PolicyDocument: {\n Statement: Match.arrayWith([\n Match.objectLike({\n Action: Match.arrayWith(['s3:GetObject*', 's3:GetBucket*']),\n Effect: 'Allow',\n }),\n ]),\n },\n });\n});\n```\n\n### Pattern: Test Cross-Stack References\n\n```typescript\ntest('app stack uses VPC from network stack', () => {\n const app = new App();\n const networkStack = new NetworkStack(app, 'Network');\n const appStack = new AppStack(app, 'App', { vpc: networkStack.vpc });\n const template = Template.fromStack(appStack);\n\n template.hasResourceProperties('AWS::Lambda::Function', {\n VpcConfig: {\n SubnetIds: Match.anyValue(),\n SecurityGroupIds: Match.anyValue(),\n },\n });\n});\n```\n\n### Pattern: Parameterized Tests\n\n```typescript\ndescribe.each([\n ['dev', false, 'PAY_PER_REQUEST'],\n ['prod', true, 'PAY_PER_REQUEST'],\n])('environment: %s', (env, pitr, billing) => {\n test(`DynamoDB has PITR=${pitr}`, () => {\n const app = new App({ context: { stage: env } });\n const stack = new MyStack(app, 'Stack');\n const template = Template.fromStack(stack);\n\n if (pitr) {\n template.hasResourceProperties('AWS::DynamoDB::Table', {\n PointInTimeRecoverySpecification: { PointInTimeRecoveryEnabled: true },\n });\n }\n });\n});\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9936,"content_sha256":"2bdcfea58322edc4e6cd8f14b712bbb79fd6394ca4aacff56357124c2d9a0312"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"AWS CDK TypeScript","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"Use this skill to build AWS infrastructure in TypeScript with reusable constructs, safe defaults, and a validation-first delivery loop.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to Use","type":"text"}]},{"type":"paragraph","content":[{"text":"Use this skill when:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Creating or refactoring a CDK app, stack, or reusable construct in TypeScript","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Choosing between L1, L2, and L3 constructs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Building serverless, networking, or security-focused AWS infrastructure","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Wiring multi-stack applications and environment-aware deployments","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validating infrastructure changes with ","type":"text"},{"text":"cdk synth","type":"text","marks":[{"type":"code_inline"}]},{"text":", tests, ","type":"text"},{"text":"cdk diff","type":"text","marks":[{"type":"code_inline"}]},{"text":", and ","type":"text"},{"text":"cdk deploy","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Instructions","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"1. Project Initialization","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Create a new CDK app\nnpx cdk init app --language typescript\n\n# Project structure\nmy-cdk-app/\n├── bin/\n│ └── my-cdk-app.ts # App entry point (instantiates stacks)\n├── lib/\n│ └── my-cdk-app-stack.ts # Stack definition\n├── test/\n│ └── my-cdk-app.test.ts # Tests\n├── cdk.json # CDK configuration\n├── tsconfig.json\n└── package.json","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"2. Core Architecture","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"import { App, Stack, StackProps, CfnOutput, RemovalPolicy } from 'aws-cdk-lib';\nimport { Construct } from 'constructs';\nimport * as s3 from 'aws-cdk-lib/aws-s3';\n\n// Define a reusable stack\nclass StorageStack extends Stack {\n public readonly bucketArn: string;\n\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n\n const bucket = new s3.Bucket(this, 'DataBucket', {\n versioned: true,\n encryption: s3.BucketEncryption.S3_MANAGED,\n removalPolicy: RemovalPolicy.RETAIN,\n blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,\n });\n\n this.bucketArn = bucket.bucketArn;\n new CfnOutput(this, 'BucketName', { value: bucket.bucketName });\n }\n}\n\n// App entry point\nconst app = new App();\n\nnew StorageStack(app, 'DevStorage', {\n env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: 'us-east-1' },\n tags: { Environment: 'dev' },\n});\n\nnew StorageStack(app, 'ProdStorage', {\n env: { account: '123456789012', region: 'eu-west-1' },\n tags: { Environment: 'prod' },\n terminationProtection: true,\n});\n\napp.synth();","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"3. Construct Levels","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Level","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use When","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"L1","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"Cfn*","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Direct CloudFormation mapping, full control","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Need properties not exposed by L2","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"L2","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Curated with sensible defaults and helper methods","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Standard resource provisioning (recommended)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"L3","type":"text","marks":[{"type":"strong"}]},{"text":" (Patterns)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Multi-resource architectures","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Common patterns like ","type":"text"},{"text":"LambdaRestApi","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"// L1 — Raw CloudFormation\nnew s3.CfnBucket(this, 'L1Bucket', { bucketName: 'my-l1-bucket' });\n\n// L2 — Sensible defaults + grant helpers\nconst bucket = new s3.Bucket(this, 'L2Bucket', { versioned: true });\nbucket.grantRead(myLambda);\n\n// L3 — Multi-resource pattern\nnew apigateway.LambdaRestApi(this, 'Api', { handler: myLambda });","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"4. CDK Lifecycle Commands","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"cdk synth # Synthesize CloudFormation template\ncdk diff # Compare deployed vs local changes\ncdk deploy # Deploy stack(s) to AWS\ncdk deploy --all # Deploy all stacks\ncdk destroy # Tear down stack(s)\ncdk ls # List all stacks in the app\ncdk doctor # Check environment setup","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"5. Recommended Delivery Loop","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Model the stack","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Start with L2 constructs and extract repeated logic into custom constructs.","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run ","type":"text","marks":[{"type":"strong"}]},{"text":"cdk synth","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Checkpoint: synthesis succeeds with no missing imports, invalid props, missing context, or unresolved references.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If it fails: fix the construct configuration or context values, then rerun ","type":"text"},{"text":"cdk synth","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run infrastructure tests","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Checkpoint: assertions cover IAM scope, stateful resources, and critical outputs.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If tests fail: update the stack or test expectations, then rerun the test suite.","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run ","type":"text","marks":[{"type":"strong"}]},{"text":"cdk diff","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Checkpoint: review IAM broadening, resource replacement, export changes, and deletes on stateful resources.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If the diff is risky: adjust names, dependencies, or ","type":"text"},{"text":"RemovalPolicy","type":"text","marks":[{"type":"code_inline"}]},{"text":", then rerun ","type":"text"},{"text":"cdk diff","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run ","type":"text","marks":[{"type":"strong"}]},{"text":"cdk deploy","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Checkpoint: the stack reaches ","type":"text"},{"text":"CREATE_COMPLETE","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"UPDATE_COMPLETE","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If deploy fails: inspect CloudFormation events, fix quotas, permissions, export conflicts, or bootstrap issues, then retry ","type":"text"},{"text":"cdk deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify runtime outcomes","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Confirm stack outputs, endpoints, alarms, and integrations behave as expected before moving on.","type":"text"}]}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"6. Cross-Stack References","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"// Stack A exports a value\nclass NetworkStack extends Stack {\n public readonly vpc: ec2.Vpc;\n constructor(scope: Construct, id: string, props?: StackProps) {\n super(scope, id, props);\n this.vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 2 });\n }\n}\n\n// Stack B imports it via props\ninterface AppStackProps extends StackProps {\n vpc: ec2.Vpc;\n}\nclass AppStack extends Stack {\n constructor(scope: Construct, id: string, props: AppStackProps) {\n super(scope, id, props);\n new lambda.Function(this, 'Fn', {\n runtime: lambda.Runtime.NODEJS_20_X,\n handler: 'index.handler',\n code: lambda.Code.fromAsset('lambda'),\n vpc: props.vpc,\n });\n }\n}\n\n// Wire them together\nconst network = new NetworkStack(app, 'Network');\nnew AppStack(app, 'App', { vpc: network.vpc });","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Examples","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example 1: Serverless API","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"import * as cdk from 'aws-cdk-lib';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport * as apigateway from 'aws-cdk-lib/aws-apigateway';\nimport * as dynamodb from 'aws-cdk-lib/aws-dynamodb';\n\nclass ServerlessApiStack extends cdk.Stack {\n constructor(scope: Construct, id: string, props?: cdk.StackProps) {\n super(scope, id, props);\n\n const table = new dynamodb.Table(this, 'Items', {\n partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },\n billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,\n removalPolicy: cdk.RemovalPolicy.DESTROY,\n });\n\n const fn = new lambda.Function(this, 'Handler', {\n runtime: lambda.Runtime.NODEJS_20_X,\n handler: 'index.handler',\n code: lambda.Code.fromAsset('lambda'),\n environment: { TABLE_NAME: table.tableName },\n });\n\n table.grantReadWriteData(fn);\n\n new apigateway.LambdaRestApi(this, 'Api', { handler: fn });\n }\n}","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Example 2: CDK Assertion Test","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"typescript"},"content":[{"text":"import { Template } from 'aws-cdk-lib/assertions';\nimport { App } from 'aws-cdk-lib';\nimport { ServerlessApiStack } from '../lib/serverless-api-stack';\n\ntest('creates DynamoDB table with PAY_PER_REQUEST', () => {\n const app = new App();\n const stack = new ServerlessApiStack(app, 'TestStack');\n const template = Template.fromStack(stack);\n\n template.hasResourceProperties('AWS::DynamoDB::Table', {\n BillingMode: 'PAY_PER_REQUEST',\n });\n\n template.resourceCountIs('AWS::Lambda::Function', 1);\n});","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Best Practices","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"One concern per stack","type":"text","marks":[{"type":"strong"}]},{"text":" — Separate network, compute, storage, and monitoring.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Prefer L2 constructs","type":"text","marks":[{"type":"strong"}]},{"text":" — Drop to ","type":"text"},{"text":"Cfn*","type":"text","marks":[{"type":"code_inline"}]},{"text":" only when you need unsupported properties.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Set explicit environments","type":"text","marks":[{"type":"strong"}]},{"text":" — Pass ","type":"text"},{"text":"env","type":"text","marks":[{"type":"code_inline"}]},{"text":" with account and region; avoid implicit production targets.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use grant helpers","type":"text","marks":[{"type":"strong"}]},{"text":" — Prefer ","type":"text"},{"text":".grant*()","type":"text","marks":[{"type":"code_inline"}]},{"text":" over handwritten IAM where possible.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Review the diff before deploy","type":"text","marks":[{"type":"strong"}]},{"text":" — Treat IAM expansion, replacement, and deletes as mandatory checkpoints.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test infrastructure","type":"text","marks":[{"type":"strong"}]},{"text":" — Cover critical resources with fine-grained assertions.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Avoid hardcoded values","type":"text","marks":[{"type":"strong"}]},{"text":" — Use context, parameters, or environment variables.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use the right ","type":"text","marks":[{"type":"strong"}]},{"text":"RemovalPolicy","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — ","type":"text"},{"text":"RETAIN","type":"text","marks":[{"type":"code_inline"}]},{"text":" for production data, ","type":"text"},{"text":"DESTROY","type":"text","marks":[{"type":"code_inline"}]},{"text":" only for disposable environments.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Constraints and Warnings","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"CloudFormation limits","type":"text","marks":[{"type":"strong"}]},{"text":" — Max 500 resources per stack; split large apps into multiple stacks","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Synthesis is not deployment","type":"text","marks":[{"type":"strong"}]},{"text":" — ","type":"text"},{"text":"cdk synth","type":"text","marks":[{"type":"code_inline"}]},{"text":" only generates templates; ","type":"text"},{"text":"cdk deploy","type":"text","marks":[{"type":"code_inline"}]},{"text":" applies changes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cross-stack references","type":"text","marks":[{"type":"strong"}]},{"text":" create CloudFormation exports; removing them requires careful ordering","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Stateful resources","type":"text","marks":[{"type":"strong"}]},{"text":" (RDS, DynamoDB, S3 with data) — Always set ","type":"text"},{"text":"removalPolicy: RETAIN","type":"text","marks":[{"type":"code_inline"}]},{"text":" in production","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Bootstrap required","type":"text","marks":[{"type":"strong"}]},{"text":" — Run ","type":"text"},{"text":"cdk bootstrap","type":"text","marks":[{"type":"code_inline"}]},{"text":" once per account/region before first deploy","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Asset bundling","type":"text","marks":[{"type":"strong"}]},{"text":" — Lambda code and Docker images are uploaded to the CDK bootstrap bucket","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"paragraph","content":[{"text":"Detailed implementation guides are available in the ","type":"text"},{"text":"references/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Core Concepts","type":"text","marks":[{"type":"link","attrs":{"href":"references/core-concepts.md","title":null}}]},{"text":" — App lifecycle, stacks, constructs, environments, assets","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Serverless Patterns","type":"text","marks":[{"type":"link","attrs":{"href":"references/serverless-patterns.md","title":null}}]},{"text":" — Lambda, API Gateway, DynamoDB, S3 events, Step Functions","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Networking & VPC","type":"text","marks":[{"type":"link","attrs":{"href":"references/networking-vpc.md","title":null}}]},{"text":" — VPC design, subnets, NAT, security groups, VPC endpoints","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Security Hardening","type":"text","marks":[{"type":"link","attrs":{"href":"references/security-hardening.md","title":null}}]},{"text":" — IAM, KMS, Secrets Manager, WAF, compliance","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Testing Strategies","type":"text","marks":[{"type":"link","attrs":{"href":"references/testing-strategies.md","title":null}}]},{"text":" — Assertions, snapshots, integration tests, CDK Nag","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"aws-cdk","author":"@skillopedia","source":{"stars":366,"repo_name":"developer-kit","origin_url":"https://github.com/giuseppe-trisciuoglio/developer-kit/blob/HEAD/plugins/developer-kit-typescript/skills/aws-cdk/SKILL.md","repo_owner":"giuseppe-trisciuoglio","body_sha256":"c55115106edb9127612eb5a84956a4559f0169321f2ddcca4287392fe0d9adc6","cluster_key":"8cae2d110d672b9518eb41adcd765857481d3396661f280b58269269d171d9c0","clean_bundle":{"format":"clean-skill-bundle-v1","source":"giuseppe-trisciuoglio/developer-kit/plugins/developer-kit-typescript/skills/aws-cdk/SKILL.md","text_bytes":47864,"source_commit":"fe73fb33a09ee6562eeec7415a3f9a3bcf795177","skills_sh_rank":5952,"attachment_count":5,"text_attachments":5,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"plugins/developer-kit-typescript/skills/aws-cdk/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"devops-infrastructure","import_tag":"skills-sh-top20k-2026-11","description":"Provides AWS CDK TypeScript patterns for defining, validating, and deploying AWS infrastructure as code. Use when creating CDK apps, stacks, and reusable constructs, modeling serverless or VPC-based architectures, applying IAM and encryption defaults, or testing and reviewing `cdk synth`, `cdk diff`, and `cdk deploy` changes. Triggers include \"aws cdk typescript\", \"create cdk app\", \"cdk stack\", \"cdk construct\", \"cdk deploy\", and \"cdk test\".","allowed-tools":"Read, Write, Edit, Bash, Grep, Glob"}},"renderedAt":1793666713319}

AWS CDK TypeScript Overview Use this skill to build AWS infrastructure in TypeScript with reusable constructs, safe defaults, and a validation-first delivery loop. When to Use Use this skill when: - Creating or refactoring a CDK app, stack, or reusable construct in TypeScript - Choosing between L1, L2, and L3 constructs - Building serverless, networking, or security-focused AWS infrastructure - Wiring multi-stack applications and environment-aware deployments - Validating infrastructure changes with , tests, , and Instructions 1. Project Initialization 2. Core Architecture 3. Construct Levels…