Nesting stacks in AWS CDK isn’t just about code organization; it fundamentally changes how CloudFormation resources are deployed and updated, often in ways that surprise developers.

Imagine you have a standard CDK application. You define your resources within a Stack. When you deploy this, CDK synthesizes a single CloudFormation template and that template creates all your resources. Simple enough.

Now, let’s introduce nesting. You create a "parent" stack, and within it, you instantiate another Stack object. This nested stack is still defined within your application’s code, but when CDK synthesizes, it doesn’t create one giant CloudFormation template. Instead, it generates a primary CloudFormation template that references a separate, nested CloudFormation template. This nested template then defines the resources for that inner stack.

Here’s a simplified look at the CDK code:

from aws_cdk import Stack, App
from constructs import Construct

class MyNestedStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)
        # Define resources within the nested stack
        # e.g., a DynamoDB table
        from aws_cdk import aws_dynamodb as ddb
        ddb.Table(self, "MyNestedTable",
                  partition_key={"name": "id", "type": ddb.AttributeType.STRING},
                  billing_mode=ddb.BillingMode.PAY_PER_REQUEST)

class MyParentStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)
        # Instantiate the nested stack
        MyNestedStack(self, "MyNestedResources")

app = App()
MyParentStack(app, "ParentStackDeployment")

When you run cdk synth, you’ll see two CloudFormation templates generated: ParentStackDeployment.template.json and MyNestedResources.template.json. The parent template will contain a AWS::CloudFormation::Stack resource that points to the S3 location of the nested template.

The core benefit of nesting is modularity and reusability. You can define common infrastructure patterns (like a standard web server setup with an ALB, Auto Scaling Group, and security groups) in a nested stack and then instantiate that pattern multiple times across different parent stacks, or even within the same parent stack, with different configurations. This promotes a DRY (Don’t Repeat Yourself) principle.

Consider a multi-account deployment where each account needs a similar set of core services. You can create a CoreServicesStack (as a nested stack) and then deploy it into each account’s main stack, passing in account-specific parameters.

However, this modularity comes with a significant trade-off: update complexity and blast radius. When you update a resource inside a nested stack, CloudFormation treats the entire nested stack as a single unit for updates. This means if you change just one small thing in your nested stack (e.g., update a tag on a Lambda function), CloudFormation will perform a replacement of the entire nested stack. This can lead to longer update times and, more importantly, a larger blast radius. If an update to the nested stack fails, CloudFormation might attempt to roll back the entire nested stack, potentially impacting all resources within it.

This is in contrast to a single, monolithic stack where individual resource updates are generally more granular. CDK’s default behavior synthesizes a single template, allowing CloudFormation to update resources more precisely.

The critical point that most people miss is how CloudFormation’s update policies apply. When a nested stack is updated, CloudFormation’s default behavior is to try and update all resources within that nested stack. If you have a resource in a nested stack that cannot be updated without replacement (like changing an RDS instance class), the entire nested stack might be replaced. This is why it’s crucial to understand that nesting creates a boundary. Changes within that boundary can trigger a full replacement of the boundary itself.

When you need to update a nested stack, you typically run cdk deploy targeting the parent stack. CDK will detect the change in the nested stack’s template and orchestrate the update. If you have custom update policies on resources within the nested stack (e.g., AutoScalingReplacingUpdate), these will still apply, but they operate within the context of the nested stack’s overall update process.

You’ll often find yourself using nested stacks for distinct, self-contained units of infrastructure that you want to manage and deploy independently, or reuse across projects. Think of it like microservices for your infrastructure. But be mindful of the operational overhead.

The next challenge you’ll likely face is managing the dependencies and ordering of operations between nested stacks, or between a nested stack and resources in its parent.

Want structured learning?

Take the full Cdk course →