AWS 376: AWS CDK constructs, stacks, stages, context, assets, and bootstrapping
Why this lesson matters
AWS CDK is code that synthesizes CloudFormation, not a replacement for infrastructure lifecycle controls. An architect must understand construct abstraction, logical identity, context, assets, environments, bootstrap trust, generated IAM, deterministic synthesis, tests, and the resulting template.
App hierarchy and abstraction
| Construct | Role | Review concern |
|---|---|---|
| App | Root synthesis unit | Environment/config selection |
| Stage | Group of stacks for an environment or wave | Promotion boundary |
| Stack | CloudFormation deployment/lifecycle unit | Ownership, failure and outputs |
| L1 construct | Direct CloudFormation resource model | Complete explicit configuration |
| L2 construct | Intent-oriented service abstraction | Defaults and generated resources |
| L3 pattern | Multi-resource architecture | Hidden permissions/cost/blast radius |
Construct IDs form paths that influence logical IDs. Renaming/moving constructs can create replacement-looking template changes. Preserve stable identity or use deliberate migration techniques after reviewing generated differences. Escape hatches can set unsupported properties but create maintenance debt; explain and test each one.
A Stage is a code organization and deployment grouping, not automatically an AWS account or CloudFormation resource. A stack is environment-specific when account/Region are fixed and can perform lookups; environment-agnostic stacks have limitations. Pass environment configuration through typed inputs, not scattered conditionals.
Context, synthesis, and testing
Context lookups query account state and cache results in cdk.context.json. Commit intended cached context so teammates and CI synthesize consistently; refresh deliberately and review the resulting infrastructure diff. Do not place secrets in context, source, outputs, or synthesized assemblies. Feature flags and CDK/library versions can change synthesis, so pin dependencies and record tool/runtime versions.
Use layers of tests: application unit logic, CDK assertions on resources/properties, snapshot only where stable and reviewed, policy/security tests, cdk synth, template linting, CloudFormation Guard or equivalent policy, cdk diff, change set, and deployed integration tests. A passing construct test does not prove service behavior.
Assets include files such as Lambda bundles and container images. Synthesis records asset manifests; publishing uploads content to bootstrap S3/ECR resources. Trace source commit to asset hash/location and final Lambda code or image digest. Exclude secrets and unnecessary files, use deterministic builds, scan artifacts, and govern retention.
Bootstrap security model
Modern bootstrapping creates a CloudFormation stack with asset bucket, ECR repository, SSM version parameter, and roles for deployment, file/image publishing, lookups, and CloudFormation execution. Bootstrap is privileged infrastructure that must be reviewed, versioned, monitored, and updated deliberately.
Cross-account trust allows approved deployment principals to assume bootstrap roles. Trust does not by itself constrain what CloudFormation can create; execution policies/permissions boundaries and pipeline policy matter. Never copy a broad --trust example into an organization without threat modeling. Protect the qualifier, bucket/key encryption, repository, role trust, and bootstrap stack from unowned change.
| Role | Typical purpose | Risk to constrain |
|---|---|---|
| Lookup | Read environment facts during synthesis | Sensitive inventory exposure |
| File/image publishing | Upload deployment assets | Artifact substitution/deletion |
| Deployment | Submit CloudFormation/assets | Cross-account assumption |
| CloudFormation execution | Provision stack resources | Broad service and IAM authority |
Local workshop
Install a pinned supported Node.js runtime and CDK CLI in an isolated project rather than globally drifting the host. Create a TypeScript app with network and workload stacks inside a stage. Use L1 and L2 resources, typed properties, tags, outputs only for nonsecrets, and one asset. Run:
npx cdk --version
npm ci
npx cdk synth --all
npx cdk list
npx cdk diff '*'
aws cloudformation describe-stacks --stack-name CDKToolkit --region ap-south-1
Do not deploy in this lesson. Inspect cdk.out: templates, metadata, asset manifest, tree, generated policies, mappings, conditions, and logical IDs. Compare two syntheses for determinism. Change a construct ID, context value, dependency version, asset byte, and environment, then explain every diff before reverting locally.
Failure and architecture exercise
Diagnose 15 cases: CLI/library mismatch, dependency drift, stale context, missing lookup access, secret in assembly, nondeterministic synth, logical-ID replacement, circular stack dependency, cross-Region reference, oversized asset, Docker unavailable, bootstrap missing/outdated, qualifier mismatch, asset KMS denial, bootstrap trust too broad, and execution-policy denial.
Design dev/test/prod environments with account/Region, bootstrap ownership/version, trust principal, execution boundary, asset encryption/retention, context refresh, tests, approvals, and recovery. Calculate resource and asset costs generated by an L3 construct rather than treating abstraction as free.
Acceptance
Submit hierarchy and environment diagrams, deterministic assembly, generated-resource/IAM inventory, context policy, asset provenance, bootstrap threat model, test layers, 16 failure results, cost, and cleanup/retention. Pass requires review of synthesized CloudFormation, pinned versions, no secrets, stable logical ownership, and bounded bootstrap trust.