A **nested stack** is a CloudFormation stack created **as a resource inside another stack**, using the `AWS::CloudFormation::Stack` resource type. The result is a hierarchy: a root stack containing nested stacks, which can themselves contain more nested stacks.
It's the in-account, in-region answer to "this template is too big" and "we keep copy-pasting the same load balancer config".
## Terminology
```
Stack A (root)
└── Stack B (child of A; A is its parent AND its root)
└── Stack C (child of B; B is parent, A is root)
└── Stack D (child of C; C is parent, A is root)
```
- **Root stack**: top of the hierarchy; the one you operate on directly
- **Parent stack**: immediate enclosing stack
- **Nested stack**: any stack referenced by another via `AWS::CloudFormation::Stack`
## The basic pattern
Parent template references a child:
```yaml
Resources:
NestedStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/my-bucket/nested-template.yaml
Parameters:
MemorySize: 256 # passed as input to the child template
```
Child template publishes outputs that the parent reads via `!GetAtt`:
```yaml
# In the parent
Outputs:
ChildLambdaArn:
Value: !GetAtt NestedStack.Outputs.LambdaArn
```
Note the `.Outputs.OutputName` syntax — it's the only place CFN reads a child output back into the parent.
## `aws cloudformation package` — the local-file workflow
`TemplateURL` must be an S3 URL at deploy time. To work locally without manually uploading every nested template, use:
```bash
aws cloudformation package \
--s3-bucket my-bucket \
--template /path/to/top-level-template.yaml \
--output-template-file packaged-template.yaml
```
This walks the template, uploads every local-file `TemplateURL` to S3, and rewrites the references to S3 URLs in the output template. Then `aws cloudformation deploy` against the packaged template.
This is the standard CDK / SAM packaging pattern, exposed as a raw CFN command.
## Operations: always work from the root
> Stack updates should be initiated from the root stack rather than performed directly on the nested stacks.
When you update the root, CFN walks the hierarchy and updates only nested stacks whose templates changed. Nested stacks that haven't changed are left alone.
If you update a nested stack directly:
- The nested stack updates fine
- The root stack now drifts from its nested stack (the root expected the old child template)
- Subsequent root-stack updates may behave unpredictably
The console marks nested stacks with a `NESTED` badge. Most teams enforce "update root only" via tooling.
## Failure mode: stuck nested stacks block the parent
> If one nested stack becomes stuck in `UPDATE_ROLLBACK_IN_PROGRESS` state, the root stack will wait until that nested stack completes its rollback before continuing.
This means a single nested-stack failure can stall the entire hierarchy. Recovery uses `continue-update-rollback` with `--resources-to-skip` (see [[CFN Failure Rollback Behavior]]). For nested-stack resources, the skip syntax is `NestedStackName.ResourceLogicalID`.
## Nested stacks vs Outputs/Exports
The User Guide is explicit about the choice:
> If you want to isolate information sharing to within a nested stack group, we suggest that you use nested stacks. To share information with other stacks (not just within the group of nested stacks), export values.
| Pattern | When |
|---------|------|
| **Nested stacks** | One team, one deploy cadence, sharing within a managed group |
| **Outputs/Exports** | Independent stacks across teams or deploy schedules; see [[CFN Cross-Stack References Outputs and ImportValue]] |
The deciding question: does the consumer stack ever get deployed *without* the producer? If yes → exports. If they always deploy together → nested.
## When nested stacks are the right tool
1. **Template size limits** — single processed template can hit the `Transformation data limit exceeded` error; splitting into nested stacks is the standard workaround
2. **Reusable subsystem** (load balancer, monitoring stack, IAM role bundle) used identically across multiple parent templates
3. **Parallel team development** — different teams own different nested stacks, but composition lives in one root template
## When NOT to use them
- Across accounts → use [[CFN StackSets Cross-Account Cross-Region]]
- Across regions → same answer
- Across independent deploy cadences → use Outputs/Exports
- For configurable variation → use Parameters + Conditions (composing nested stacks with different parameters often overcomplicates)
## Capabilities flag for IAM resources
When the parent or any nested stack creates IAM resources, deploy with `--capabilities CAPABILITY_IAM` or `CAPABILITY_NAMED_IAM`:
```bash
aws cloudformation deploy --template-file packaged.yaml \
--stack-name my-stack \
--capabilities CAPABILITY_NAMED_IAM
```
This is CFN's "yes, I know IAM is being modified" acknowledgment — protects against templates that silently grant excess permissions.
## Related
- [[CFN Stack Concept]]
- [[CFN Cross-Stack References Outputs and ImportValue]]
- [[CFN StackSets Cross-Account Cross-Region]]
- [[CFN Failure Rollback Behavior]]