AWS 373: Change sets, nested stacks, modules, imports, and custom resources
Why this lesson matters
Advanced CloudFormation mechanisms solve different problems. Change sets preview proposed actions, nested stacks split lifecycle boundaries, modules package reusable fragments, imports adopt existing resources, and custom resources extend the provider. Misusing one can hide replacement, couple teams, or strand production resources.
Selection model
| Mechanism | Use it for | Primary risk |
|---|---|---|
| Change set | Review add/modify/remove/import before execution | Preview cannot predict every runtime failure |
| Nested stack | One parent-owned deployment decomposed into stacks | Coupled root lifecycle and output contracts |
| Module | Reusable versioned template fragment | Hidden expansion and version governance |
| Resource import | Bring supported existing resource under management | Incorrect model causes drift/update risk |
| Custom resource | Idempotent lifecycle not natively supported | Callback timeout, security, duplicate side effects |
Change sets describe actions and replacement likelihood from the proposed template and current model. Review logical/physical IDs, details, scope, replacement, removals, condition changes, IAM capabilities, parameter changes, and expanded nested hierarchy. Execution still can fail from quota, permissions, service state, custom logic, or concurrent changes. Delete stale change sets and prevent execution after its assumptions expire.
Composition boundaries
A nested stack is an AWS::CloudFormation::Stack resource whose template normally resides in S3. Pass parameters down and return Outputs up; avoid circular dependencies and giant cross-stack export graphs. The root should own updates and change sets. Design boundaries by lifecycle/ownership and failure domain, not merely file length.
Modules are registered/versioned packages expanded into generated resources. Pin and govern versions, inspect processed templates/change sets, test upgrades, document exposed parameters/outputs, and retain provenance. A module is not an independent running stack.
Import and refactoring
Inventory the physical resource, supported import method, identifier, current configuration, tags, dependencies, policy, encryption, and data protection. Write a template that accurately describes it and include retention protection before import. Create and review an import change set; never guess identifiers in production.
Import does not transform the resource to match every property during adoption. After successful import, run drift detection and reconcile intentionally through a separate reviewed update. For refactoring between stacks, plan export/import dependencies, retention, name uniqueness, rollback, and an interval where ownership is unambiguous. Do not let two stacks manage one resource.
Record an ownership ledger before and after refactoring: logical ID, physical ID, source stack, destination stack, retention policy, dependent exports, data owner, and rollback boundary. Pause unrelated deployments during the ownership transition. A successful import is only the control-plane handoff; application traffic, policies, alarms, backup jobs, and cost allocation must still be verified against the unchanged physical resource.
Custom-resource protocol
CloudFormation sends create, update, and delete requests containing a request ID, stack/logical identity, properties, and response location. The provider must send one terminal response before timeout. Keep a stable physical resource ID when an update is in place; changing it signals replacement and later deletion of the old identity.
Handlers must be idempotent for duplicate delivery, authenticate the request context, protect the response URL, avoid secrets in data/reason/logs, bound retries, and make delete tolerate an absent resource. Use asynchronous provider frameworks where long operations require callbacks. A failed delete can block an entire stack deletion.
Read-only inspection and workshop
aws cloudformation list-change-sets --stack-name STACK --region ap-south-1
aws cloudformation describe-change-set --change-set-name CHANGE_SET --stack-name STACK --include-property-values --region ap-south-1
aws cloudformation get-template --stack-name STACK --template-stage Processed --region ap-south-1
aws cloudformation list-stack-resources --stack-name STACK --region ap-south-1
aws cloudformation describe-type --type MODULE --type-name MODULE_NAME --region ap-south-1
Design a root application with network, data, and workload nested stacks; one pinned module; one supplied existing bucket import; and one custom resource that registers an external test record. Produce parameter/output contracts, generated-resource inventory, import dossier, custom-resource state machine, and root change-set review.
Inject 14 failures: unexpected replacement, stale change set, nested output rename, S3 template denial, circular export, module version drift, unsupported import, wrong identifier, inaccurate property, two-stack ownership, provider permission denial, missing callback, duplicate create, changed physical ID, and failed delete. For each give evidence, blast radius, rollback/forward action, and final ownership.
Cost and acceptance
Price S3 templates/artifacts, module registry/testing, Lambda/provider compute and logs, retained/imported resources, failed duplicates, and engineer operations. This lesson creates nothing. Live cleanup must remove only owned test stacks/providers and verify retained/imported resources separately.
Submit the selection table, hierarchy, contracts, processed-template review, change set, import plan and drift result, provider pseudocode/state machine, fifteen failure results, security model, cost, and cleanup. Pass requires explicit ownership, no blind change-set trust, safe import protection, pinned reuse, and idempotent custom lifecycle handling.