AWS CDK
Overview
Domain expertise for CDK construct authoring, deployment workflows, compliance, drift, importing resources, safe refactoring, and troubleshooting CDK CLI / CloudFormation errors.
When NOT to use: Raw CloudFormation YAML/JSON. SAM. Terraform/Pulumi. CI/CD beyond CDK Pipelines. Use builtin knowledge or specialized skills for these.
Critical Warnings
Deadly embrace: Removing a cross-stack reference deadlocks deployment (Export ... cannot be deleted as it is in use by ...). Preferred fix: weaken the reference first — CrossStackReferences.of($RESOURCE).produce(ReferenceStrength.BOTH) then WEAK, then remove (three deploys). Legacy fallback: two-deploy this.exportValue() recipe. See troubleshooting-deployment.
Construct ID changes cause replacement: Renaming/moving a construct changes its logical ID → CloudFormation replaces the resource (data loss for stateful resources). Always cdk diff before deploy. See refactor-and-prevent-replacement.
UPDATE_ROLLBACK_FAILED: Stack is stuck. Fix with cdk rollback $STACK or cdk rollback $STACK --orphan <LogicalId>. See troubleshooting-deployment.
Non-empty S3 buckets persist after destroy: You MUST set both removalPolicy: DESTROY and autoDeleteObjects: true. Versioned buckets are worse — delete markers persist even after apparent deletion.
Common Workflows
| Task |
Quick Command |
Details |
| Bootstrap |
cdk bootstrap aws://$ACCOUNT/$REGION |
bootstrap-and-project-setup |
| New TS project |
cdk init app --language typescript — use tsx, eslint-plugin-awscdk |
bootstrap-and-project-setup |
| New Python project |
cdk init app --language python — pin deps, use virtualenv |
bootstrap-and-project-setup |
| Deploy |
cdk synth --strict → cdk diff → cdk deploy |
Always diff before deploy to prod |
| cdk-nag |
Aspects.of(app).add(new AwsSolutionsChecks()) |
compliance-and-drift |
| Drift |
cdk drift $STACK (use --fail in CI) |
compliance-and-drift |
| Import resource |
cdk import (interactive or --resource-mapping for CI), cdk deploy --import-existing-resources |
import-and-migrate |
| Refactor safely |
cdk refactor --unstable=refactor — no property changes in same deploy |
refactor-and-prevent-replacement |
Troubleshooting
| Error |
Cause → Fix |
| DeployFailed / DeploymentError |
CDK error isn't the root cause. cdk deploy $STACK --verbose, then cdk --unstable=diagnose diagnose $STACK (CLI ≥ 2.1120.0); else aws cloudformation describe-events --stack-name $STACK --filters FailedEvents=true — the first _FAILED event is the cause. Details |
| NoCredentials / ExpiredToken / AssumeRoleFailed |
aws sts get-caller-identity + cdk doctor. Expired SSO, missing env, missing sts:AssumeRole. Details |
| Asset errors (CannotFindAsset, FailedToBundleAsset, AssetBuildFailed, AssetPublishFailed) |
Path wrong, Docker not running, or bootstrap bucket perms. Use path.join(__dirname, ...). Details |
| AppRequired |
Add "app": "npx tsx bin/my-app.ts" to cdk.json. Details |
| AnnotationErrors |
Fix the underlying issue; suppress with NagSuppressions only as last resort. Details |
| ConcurrentReadLock / ConcurrentWriteLock |
rm -rf cdk.out then re-run. Parallel CI: --output ./cdk.out.$BUILD_ID. Details |
| BootstrapVersionValidation |
Re-bootstrap. Match --qualifier everywhere. Details |
| DependencyCycle |
Extract shared resource into third stack or use SSM for late-binding. Details |
| UnresolvedAccount |
Set explicit env: { account, region } on stack. Commit cdk.context.json. Details |
| NoStacksMatched |
CDK uses logical ID (2nd constructor arg), not CFN name. cdk list to find IDs. Details |
| Cannot find module (synth time) |
Run npx tsc --noEmit, check cdk.json app path matches tsconfig.json outDir, delete stale .js files. Python: activate venv. Details |
| V1 import paths / duplicate aws-cdk-lib |
V1 @aws-cdk/* imports, wrong Construct import, duplicate lib copies in monorepos. Details |
| Lambda Cannot find module (runtime) |
Wrong handler value, missing SDK v3 migration, Python deps not bundled. Details |
| API Gateway multi-stage conflicts |
Set deploy: false on RestApi, create Deployment and Stage explicitly. Details |
Construct Patterns
Prefer L2. Use L1 with Mixins/Facades when L2 lacks a property. Escape hatches: node.defaultChild → addPropertyOverride. See construct-patterns.
Additional Resources
- Search AWS documentation for "CDK Developer Guide", "CDK API Reference" and "CDK Pipelines" respectively
Security Considerations
- OIDC for CI/CD credentials (no static keys)
--custom-permissions-boundary on bootstrap
grant*() for inter-resource IAM
cdk-nag + --strict in CI
- Stateful resources in own stack with
terminationProtection: true
- Commit
cdk.context.json
1---2name: aws-cdk3description: Authors, deploys, and troubleshoots AWS infrastructure using CDK with TypeScript or Python. Covers best practices, stack architecture, and construct patterns. Always use when writing CDK constructs, bootstrapping environments, running cdk deploy/synth/diff, fixing CDK or CloudFormation errors, planning stack structure, importing existing resources, resolving drift, or refactoring stacks without resource replacement.4---56# AWS CDK78## Overview910Domain expertise for CDK construct authoring, deployment workflows, compliance, drift, importing resources, safe refactoring, and troubleshooting CDK CLI / CloudFormation errors.1112**When NOT to use:** Raw CloudFormation YAML/JSON. SAM. Terraform/Pulumi. CI/CD beyond CDK Pipelines. Use builtin knowledge or specialized skills for these.1314## Critical Warnings1516**Deadly embrace**: Removing a cross-stack reference deadlocks deployment (`Export ... cannot be deleted as it is in use by ...`). Preferred fix: weaken the reference first — `CrossStackReferences.of($RESOURCE).produce(ReferenceStrength.BOTH)` then `WEAK`, then remove (three deploys). Legacy fallback: two-deploy `this.exportValue()` recipe. See [troubleshooting-deployment](references/troubleshooting-deployment.md).1718**Construct ID changes cause replacement**: Renaming/moving a construct changes its logical ID → CloudFormation replaces the resource (data loss for stateful resources). Always `cdk diff` before deploy. See [refactor-and-prevent-replacement](references/refactor-and-prevent-replacement.md).1920**UPDATE_ROLLBACK_FAILED**: Stack is stuck. Fix with `cdk rollback $STACK` or `cdk rollback $STACK --orphan <LogicalId>`. See [troubleshooting-deployment](references/troubleshooting-deployment.md).2122**Non-empty S3 buckets persist after destroy**: You MUST set both `removalPolicy: DESTROY` and `autoDeleteObjects: true`. Versioned buckets are worse — delete markers persist even after apparent deletion.2324## Common Workflows2526| Task | Quick Command | Details |27|------|--------------|---------|28| Bootstrap | `cdk bootstrap aws://$ACCOUNT/$REGION` | [bootstrap-and-project-setup](references/bootstrap-and-project-setup.md) |29| New TS project | `cdk init app --language typescript` — use `tsx`, `eslint-plugin-awscdk` | [bootstrap-and-project-setup](references/bootstrap-and-project-setup.md) |30| New Python project | `cdk init app --language python` — pin deps, use virtualenv | [bootstrap-and-project-setup](references/bootstrap-and-project-setup.md) |31| Deploy | `cdk synth --strict` → `cdk diff` → `cdk deploy` | Always diff before deploy to prod |32| cdk-nag | `Aspects.of(app).add(new AwsSolutionsChecks())` | [compliance-and-drift](references/compliance-and-drift.md) |33| Drift | `cdk drift $STACK` (use `--fail` in CI) | [compliance-and-drift](references/compliance-and-drift.md) |34| Import resource | `cdk import` (interactive or `--resource-mapping` for CI), `cdk deploy --import-existing-resources` | [import-and-migrate](references/import-and-migrate.md) |35| Refactor safely | `cdk refactor --unstable=refactor` — no property changes in same deploy | [refactor-and-prevent-replacement](references/refactor-and-prevent-replacement.md) |3637## Troubleshooting3839| Error | Cause → Fix |40|-------|------------|41| **DeployFailed / DeploymentError** | CDK error isn't the root cause. `cdk deploy $STACK --verbose`, then `cdk --unstable=diagnose diagnose $STACK` (CLI ≥ 2.1120.0); else `aws cloudformation describe-events --stack-name $STACK --filters FailedEvents=true` — the first `_FAILED` event is the cause. [Details](references/troubleshooting-deployment.md) |42| **NoCredentials / ExpiredToken / AssumeRoleFailed** | `aws sts get-caller-identity` + `cdk doctor`. Expired SSO, missing `env`, missing `sts:AssumeRole`. [Details](references/troubleshooting-credentials.md) |43| **Asset errors** (CannotFindAsset, FailedToBundleAsset, AssetBuildFailed, AssetPublishFailed) | Path wrong, Docker not running, or bootstrap bucket perms. Use `path.join(__dirname, ...)`. [Details](references/troubleshooting-synth.md) |44| **AppRequired** | Add `"app": "npx tsx bin/my-app.ts"` to `cdk.json`. [Details](references/troubleshooting-synth.md) |45| **AnnotationErrors** | Fix the underlying issue; suppress with `NagSuppressions` only as last resort. [Details](references/troubleshooting-synth.md) |46| **ConcurrentReadLock / ConcurrentWriteLock** | `rm -rf cdk.out` then re-run. Parallel CI: `--output ./cdk.out.$BUILD_ID`. [Details](references/troubleshooting-synth.md) |47| **BootstrapVersionValidation** | Re-bootstrap. Match `--qualifier` everywhere. [Details](references/troubleshooting-credentials.md) |48| **DependencyCycle** | Extract shared resource into third stack or use SSM for late-binding. [Details](references/troubleshooting-synth.md) |49| **UnresolvedAccount** | Set explicit `env: { account, region }` on stack. Commit `cdk.context.json`. [Details](references/troubleshooting-credentials.md) |50| **NoStacksMatched** | CDK uses logical ID (2nd constructor arg), not CFN name. `cdk list` to find IDs. [Details](references/troubleshooting-synth.md) |51| **Cannot find module** (synth time) | Run `npx tsc --noEmit`, check `cdk.json` app path matches `tsconfig.json` `outDir`, delete stale `.js` files. Python: activate venv. [Details](references/troubleshooting-synth.md) |52| **V1 import paths / duplicate aws-cdk-lib** | V1 `@aws-cdk/*` imports, wrong `Construct` import, duplicate lib copies in monorepos. [Details](references/v1-to-v2-migration.md) |53| **Lambda Cannot find module** (runtime) | Wrong handler value, missing SDK v3 migration, Python deps not bundled. [Details](references/troubleshooting-deployment.md) |54| **API Gateway multi-stage conflicts** | Set `deploy: false` on `RestApi`, create `Deployment` and `Stage` explicitly. [Details](references/troubleshooting-deployment.md) |5556## Construct Patterns5758Prefer L2. Use L1 with Mixins/Facades when L2 lacks a property. Escape hatches: `node.defaultChild` → `addPropertyOverride`. See [construct-patterns](references/construct-patterns.md).5960## Additional Resources6162- Search AWS documentation for "CDK Developer Guide", "CDK API Reference" and "CDK Pipelines" respectively6364## Security Considerations6566- OIDC for CI/CD credentials (no static keys)67- `--custom-permissions-boundary` on bootstrap68- `grant*()` for inter-resource IAM69- `cdk-nag` + `--strict` in CI70- Stateful resources in own stack with `terminationProtection: true`71- Commit `cdk.context.json`