Synthesize only stacks you need in CDK

CDK documentation states that if you supply stack name(s) to CLI commands like cdk synth, cdk list, or cdk deploy – it will synthesize only the stacks you requested. But in reality this is not the case, CDK will always synthesize all stacks – and it may lead to unintended consequences.

Let’s say you have following stack declarations in your lib/my-stacks.ts code:

import * as cdk from 'aws-cdk-lib';
 
export class Stack1 extends cdk.Stack {};
export class Stack2 extends cdk.Stack {};
export class AnotherStack extends cdk.Stack {};
export class YerAnotherStack extends cdk.Stack {};

And in your app’s entry point bin/my-stacks.ts you instantiate those stacks:

import * as cdk from 'aws-cdk-lib';
import * as stacks from '../lib/my-stacks'
 
const app = new cdk.App();
 
new stacks.Stack1(app, "Stack1");
new stacks.Stack2(app, "Stack2");
new stacks.AnotherStack(app, "AnotherStack");
new stacks.YerAnotherStack(app, "YetAnotherStack");

And then issue a CLI command to synthesize stacks, but you only want to synthesize “Stack1” and “AnotherStack”:

cdk synth Stack1 AnotherStack

The command output would have you believe that only 2 stacks were synthesized:

Successfully synthesized to ./cdk.out
Supply a stack id (AnotherStack, Stack1) to display its template.

But if you actually look into cdk.out folder – you will see all stack templates were synthesized:

AnotherStack.assets.json        Stack2.assets.json
AnotherStack.template.json      Stack2.template.json
Stack1.assets.json              YetAnotherStack.assets.json
Stack1.template.json            YetAnotherStack.template.json

CDK will synthesize templates for all stacks you instantiate no matter what stack names you pass – the names will only be used to filter the results. In order to synthesize only the stacks you request – only classes for the stacks you request must be instantiated. We can pass the stack names to a CDK command using context via option --context or its shorter form -c:

cdk synth -c stacks=Stack1,AnotherStack

And this is how we can interpret this in our entry point code:

import * as cdk from 'aws-cdk-lib';
import * as stacks from '../lib/my-stacks'
 
const app = new cdk.App();
const myStacks: string = app.node.tryGetContext('stacks');
 
Object.entries(stacks).forEach(([stackName, stack]) => {
  if (!myStacks || myStacks.split(',').includes(stackName)) {
    new stack(app, stackName)
  }
})

Here on Line 05 we read the context parameter we passed in the command line. And on Lines 07-11 we loop thru imported stacks. If stack name matches one of the names we passed as a parameter – only then it will be instantiated. If the -c stacks parameter isn’t passed – the value will be undefined – and all stacks will be instantiated and therefore synthesized.

Now, if you issue the command (don’t forget to clear previous content of cdk.out):

cdk synth -c stacks=Stack1,AnotherStack

The output will be the same as before:

Successfully synthesized to ./cdk.out
Supply a stack id (AnotherStack, Stack1) to display its template.

But if you look into cdk.out directory – you will only see requested stacks synthesized:

]AnotherStack.assets.json
AnotherStack.template.json
Stack1.assets.json
Stack1.template.json

Leave a Reply

Your email address will not be published. Required fields are marked *