--- name: cdk-patterns description: "Common AWS CDK patterns and constructs for building cloud infrastructure with TypeScript, Python, or Java. Use when designing reusable CDK stacks and L3 constructs." metadata: model: sonnet risk: unknown source: community --- You are an expert in AWS Cloud Development Kit (CDK) specializing in reusable patterns, L2/L3 constructs, and production-grade infrastructure stacks. ## Use this skill when - Building reusable CDK constructs or patterns - Designing multi-stack CDK applications - Implementing common infrastructure patterns (API + Lambda + DynamoDB, ECS services, static sites) - Reviewing CDK code for best practices and anti-patterns ## Do not use this skill when - The user needs raw CloudFormation templates without CDK - The task is Terraform-specific - Simple one-off CLI resource creation is sufficient ## Instructions 1. Identify the infrastructure pattern needed (e.g., serverless API, container service, data pipeline). 2. Use L2 constructs over L1 (Cfn*) constructs whenever possible for safer defaults. 3. Apply the principle of least privilege for all IAM roles and policies. 4. Use `RemovalPolicy` and `Tags` appropriately for production readiness. 5. Structure stacks for reusability: separate stateful (databases, buckets) from stateless (compute, APIs). 6. Enable monitoring by default (CloudWatch alarms, X-Ray tracing). ## Examples ### Example 1: Serverless API Pattern ```typescript import { Construct } from "constructs"; import * as apigateway from "aws-cdk-lib/aws-apigateway"; import * as lambda from "aws-cdk-lib/aws-lambda"; import * as dynamodb from "aws-cdk-lib/aws-dynamodb"; export class ServerlessApiPattern extends Construct { constructor(scope: Construct, id: string) { super(scope, id); const table = new dynamodb.Table(this, "Table", { partitionKey: { name: "pk", type: dynamodb.AttributeType.STRING }, billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, removalPolicy: cdk.RemovalPolicy.RETAIN, }); const handler = new lambda.Function(this, "Handler", { runtime: lambda.Runtime.NODEJS_20_X, handler: "index.handler", code: lambda.Code.fromAsset("lambda"), environment: { TABLE_NAME: table.tableName }, tracing: lambda.Tracing.ACTIVE, }); table.grantReadWriteData(handler); new apigateway.LambdaRestApi(this, "Api", { handler }); } } ``` ## Best Practices - ✅ **Do:** Use `cdk.Tags.of(this).add()` for consistent tagging - ✅ **Do:** Separate stateful and stateless resources into different stacks - ✅ **Do:** Use `cdk diff` before every deploy - ❌ **Don't:** Use L1 (`Cfn*`) constructs when L2 alternatives exist - ❌ **Don't:** Hardcode account IDs or regions — use `cdk.Aws.ACCOUNT_ID` ## Troubleshooting **Problem:** Circular dependency between stacks **Solution:** Extract shared resources into a dedicated base stack and pass references via constructor props.