skip to content

Synth, Bootstrap, and Deploy

cdk synth turns my program into a cloud assembly of templates and assets, and bootstrap is the one-time setup people always forget. Escape hatches let me reach the raw CloudFormation when a construct falls short.

on this pageshow

questions

6

In the AWS CDK, what does the `cdk synth` command actually do, and what does it leave behind in the cdk.out directory?

level: juniorimportance: must knowfreq 70%

answer

  1. your program runs, a template comes out
  2. output directory, not a deployment
  3. one template per stack, plus a manifest
  4. cdk.out is the cloud assembly
  5. loops resolve before CloudFormation sees anything

basics

~10 s

cdk synth runs your CDK program and writes a cloud assembly into cdk.out: one CloudFormation template per stack, asset manifests, and staged asset files. It deploys nothing and changes no AWS resources.

solid answer

~40 s

`cdk synth` is the synthesis step. The CLI runs the `app` command from cdk.json — your TypeScript, Python, Java or Go program — and every construct you instantiated renders itself into CloudFormation. The result is a **cloud assembly**: a directory, `cdk.out` by default, holding `<StackName>.template.json` for each stack, a `manifest.json` describing the stacks and their target environments, `<StackName>.assets.json` listing file and image assets, `tree.json`, and the staged `asset.<hash>` files themselves. With a single stack the template is also printed to stdout. Nothing is deployed — synthesis produces an artifact. That artifact is what CI passes around: you can synthesize once and later run `cdk deploy --app cdk.out` against exactly the assembly you reviewed. Your loops and conditionals do not survive into the template; only their result does.

code

bash · 3 lines
bash
cdk synth --quiet
ls cdk.out
# cdk.out  manifest.json  tree.json  MyStack.assets.json  MyStack.template.json

go deeper

for a junior

Be able to say plainly that cdk synth runs your program and writes CloudFormation templates into cdk.out, and that it deploys nothing. Knowing where to open the generated template is half the value.

for a middle

Explain the cloud assembly's contents — template per stack, manifest, asset manifest, staged assets — and that your language's control flow is evaluated during synthesis, so only its result reaches the template.

for a senior

Show why the cloud assembly is the right CI artifact: synthesize once, publish cdk.out, and deploy that same assembly into each environment so the reviewed output is the deployed output.

for a principal

Frame synthesis as the boundary between a program and a declarative artifact, and own the consequences: reproducible builds, what determinism you can promise reviewers, and where the organization pins that artifact in its delivery flow.

## What synthesis actually is The CDK is not a template language with extra syntax. A CDK app is an ordinary program in a general-purpose language, and running it is the whole point of `cdk synth`. The CLI reads `cdk.json`, finds the `app` entry (something like `"app": "npx ts-node --prefer-ts-exts bin/app.ts"`), and executes it as a subprocess. Your program constructs an `App`, adds one or more `Stack`s to it, and adds constructs to those stacks — building an in-memory tree. At the end, `app.synth()` walks that tree, asks each construct to render itself, and writes the result to disk. What each construct renders is CloudFormation. A high-level construct may expand into many resources, IAM policies and log groups; a low-level `Cfn*` resource maps to exactly one. Either way the output is plain CloudFormation JSON — there is no CDK runtime in AWS, and nothing in the deployed account knows your app was written in TypeScript. ## What lands in cdk.out The directory the CLI writes is called a *cloud assembly*, and it is a self-describing artifact: ``` cdk.out/ cdk.out # marks the directory, with the assembly schema version manifest.json # the stacks, their environments, and their dependencies tree.json # the construct tree, used by tooling MyStack.template.json # one CloudFormation template per stack MyStack.assets.json # the file and image assets this stack needs asset.3f9c.../ # staged asset content, named by content hash ``` Every stack in the app gets its own template file, regardless of how many you asked for on the command line. `manifest.json` is what tells the CLI which account and region each stack targets and in what order dependent stacks must go out. ## Your code runs now, not at deploy time This is the point juniors most often miss. A `for` loop that creates ten buckets produces ten `AWS::S3::Bucket` resources in the template — there is no loop in the template, because the loop already ran on your laptop. An `if` on an environment name picks a branch at synthesis time and the other branch simply does not exist in the output. Anything you want CloudFormation itself to decide at deploy time has to be expressed as CloudFormation constructs, not as language constructs. Values that genuinely are not known until deploy — the ARN of a resource being created in this very deployment, for example — appear in the template as *tokens*: opaque placeholder strings during synthesis that render into CloudFormation references in the output. That is why printing such a value in your program shows something like `${Token[TOKEN.42]}` rather than a real ARN. ## Why the artifact matters Because synthesis is deterministic and local, the cloud assembly is a reviewable, storable build output. A pipeline typically synthesizes once, publishes `cdk.out` as a build artifact, and every later stage deploys *that* assembly with `cdk deploy --app cdk.out` instead of re-running the program. That removes a whole class of surprises where the code drifted, a dependency resolved differently, or a lookup returned something new between the review and the deploy. `cdk.out` is a build output and belongs in `.gitignore`. You regenerate it; you never hand-edit it. If you find yourself wanting to edit the template, that is a signal to reach for an escape hatch in the program instead, so the change survives the next synth. ## What synth does not do It does not create, modify or delete anything in AWS — you can run it with no credentials at all, unless your app performs environment lookups that need to call AWS. It does not ask CloudFormation whether the template is acceptable, so an invalid property value, a service quota, or a name collision surfaces later during deploy, not here. It does not compare against what is deployed — that is `cdk diff`. And it does not publish assets; it only *stages* them into `cdk.out` and records their hashes, leaving the upload to deploy time. The practical takeaway for an interview: synth is "run my program, get templates". Everything that touches AWS happens afterwards.

  • If I never run cdk synth and go straight to cdk deploy, does synthesis still happen?
    Yes. `cdk deploy` synthesizes first and then deploys the resulting assembly, so running `cdk synth` separately is only about seeing the output. The exception is when you point the CLI at an assembly that already exists: `cdk deploy --app cdk.out` skips running your program and deploys exactly what is on disk, which is how pipelines guarantee that the reviewed artifact is the deployed one.
  • Should cdk.out be committed to the repository?
    No — it is a build output, regenerated on every synth, and it is in the default `.gitignore` a new project ships with. Committing it invites someone to edit a template by hand, and that edit vanishes on the next synthesis. If you need the exact artifact later, publish `cdk.out` from CI as a build artifact rather than into git.

saying these in an interview costs you the question

  • Says cdk synth contacts AWS and creates resources
  • Thinks synth is a syntax transform that keeps loops in the template
  • Believes you must run synth manually before every deploy
  • Expects cdk synth to validate the template against the CloudFormation service
  • Treats cdk.out as source to be committed and hand-edited

context

open as a page

A colleague runs `cdk deploy` for the first time in a fresh AWS account and region, and it fails saying the environment has not been bootstrapped. What does `cdk bootstrap` create, and why does the AWS CDK need it?

level: middleimportance: must knowfreq 72%

basics

~20 s

cdk bootstrap deploys a CloudFormation stack named CDKToolkit into each target account and region. It provisions the asset staging S3 bucket, an ECR repository for image assets, and the IAM roles the CDK CLI assumes to publish assets and run CloudFormation.

open as a page

A CDK stack defines a Lambda function with `lambda.Code.fromAsset('./handler')` and a container image built from a local Dockerfile. Walk through what `cdk deploy` does with those assets before CloudFormation ever updates the stack.

level: middleimportance: should knowfreq 48%

basics

~20 s

Synthesis stages each asset into cdk.out and records a content hash in the stack's asset manifest. cdk deploy then publishes the zip to the bootstrap staging S3 bucket and the image to the bootstrap ECR repository, and only then updates the stack.

open as a page

In the AWS CDK, what does `cdk diff` compare, and what will it fail to warn you about before a deploy?

level: middleimportance: should knowfreq 55%

basics

~20 s

cdk diff synthesizes locally and compares that template against the template CloudFormation currently stores for the deployed stack, printing resource, IAM and security-group changes. It compares templates, not live resources, so console-made drift is invisible to it.

open as a page

An AWS CDK L2 construct does not expose a CloudFormation property you need to set. How do you set it anyway, and what do you give up by doing so?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Reach the underlying L1 resource through the construct's node.defaultChild, cast it to its Cfn type, and call addPropertyOverride or addOverride with the raw CloudFormation property path. The override is applied at synth time and the CDK does not type-check or validate it.

open as a page

Your team deploys a CDK app to dev and prod accounts from a CI job that runs `cdk deploy`. What would moving to a self-mutating CDK Pipeline (the `pipelines.CodePipeline` construct) change, and when would you keep the plain CI job?

level: principalimportance: nice to knowfreq 30%

basics

~20 s

A CDK Pipeline defines the delivery pipeline in CDK itself and updates itself: each run synthesizes, redeploys the pipeline stack from that assembly, then runs the application stages. You gain pipeline-as-code across accounts; you take on AWS-native lock-in, a privileged self-modifying pipeline, and slow feedback.

open as a page