skip to content

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%

answer

  1. one-time setup per environment
  2. environment means account plus region
  3. a stack called CDKToolkit
  4. staging bucket, ECR repo, deploy roles
  5. the qualifier in every resource name

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.

solid answer

~50 s

Bootstrapping is a one-time-per-environment setup, where an environment is one account **and** one region. `cdk bootstrap aws://123456789012/eu-west-1` deploys a stack called `CDKToolkit` containing the resources every CDK deployment depends on: an S3 staging bucket for file assets, an ECR repository for container image assets, an SSM parameter holding the bootstrap version, and a set of IAM roles — file-publishing, image-publishing, lookup, deploy, and the CloudFormation execution role that actually creates your resources. Synthesized templates and asset manifests refer to those resources by a naming convention keyed on the *qualifier* (default `hnb659fds`), so a deploy into an un-bootstrapped environment has nothing to assume and nothing to upload to, and the CLI stops with the error your colleague saw. You re-run bootstrap per new account/region, when the required bootstrap version rises, and with `--trust` when a pipeline in another account must deploy here.

go deeper

for a junior

Recognise the not-bootstrapped error and know the fix is to run cdk bootstrap against that account and region once, before any deployment there succeeds.

for a middle

List what the CDKToolkit stack provisions — staging bucket, ECR repository, version parameter and the deploy and publishing roles — and explain that a bootstrap covers one account/region pair only.

for a senior

Demonstrate ownership of the role split: what the CloudFormation execution role's policies should be, why --trust is needed for cross-account pipelines, and why the staging bucket is production infrastructure.

for a principal

Own bootstrap as an account-provisioning concern: who is allowed to run it, how execution-role permissions are scoped organization-wide, and how bootstrap version upgrades are rolled out across many accounts without breaking deployments.

## Why a bootstrap step exists at all A CloudFormation template can be handed to the service as a file, but a realistic CDK app needs more than a template. It needs somewhere to put a Lambda zip, a Docker image, or a template too large to submit inline. It needs a principal to run the deployment as. Those things cannot live inside the deployment they enable, so the CDK carves them out into a separate, long-lived stack that you create once per environment: `CDKToolkit`. An *environment* in CDK terms is the pair (account, region). Two accounts times three regions is six bootstraps. Forgetting this is the single most common first-day CDK failure, and recognising the error message is the interview answer. ## What the CDKToolkit stack contains Under the modern (default) bootstrap template in CDK v2 you get roughly: - **A staging S3 bucket** — `cdk-<qualifier>-assets-<account>-<region>` — where file assets (Lambda bundles, large templates) are uploaded before the stack update. - **An ECR repository** — `cdk-<qualifier>-container-assets-<account>-<region>` — for Docker image assets. - **An SSM parameter**, `/cdk-bootstrap/<qualifier>/version`, holding the bootstrap version number. The CLI reads it to decide whether this environment is bootstrapped and recent enough. - **IAM roles**: a file-publishing role, an image-publishing role, a lookup role (read-only, used for environment lookups), a deploy role that the CLI assumes to talk to CloudFormation, and a **CloudFormation execution role** that CloudFormation itself assumes to create your resources. The role split is the security story worth telling. The credentials a developer or a CI job holds only need to assume the deploy and publishing roles; they never need direct permission to create your infrastructure. The permissions to actually build resources sit on the CloudFormation execution role, which is set at bootstrap time with `--cloudformation-execution-policies`. Many teams point that at `AdministratorAccess` for convenience — that is a real decision to defend, and narrowing it is a legitimate hardening step. ## The qualifier Every bootstrapped resource name embeds a nine-character qualifier, `hnb659fds` by default. It exists so more than one bootstrap can coexist in an account without name collisions — for example, a team that wants an isolated toolkit with tighter execution policies. If you bootstrap with `--qualifier`, your app must be told the same qualifier (through the stack synthesizer's configuration or the `@aws-cdk/core:bootstrapQualifier` context key), otherwise it synthesizes references to resources that do not exist. ## How a deploy uses it Synthesis bakes the convention into the output. The stack's template and its `assets.json` name the staging bucket, the ECR repository and the role ARNs to assume. `cdk deploy` then: assumes the publishing roles and uploads assets; assumes the deploy role; and calls CloudFormation, passing the execution role. Nothing in that chain works in an environment with no `CDKToolkit` stack — hence a hard failure before any change is attempted, which is the friendly behaviour. ## Cross-account and re-bootstrapping Two flags matter beyond the first run. `--trust <account>` tells this environment to let roles from another account (typically the account hosting a delivery pipeline) assume its deploy and publishing roles — the prerequisite for any cross-account CDK pipeline. `--cloudformation-execution-policies` sets what the execution role may do, and is required when you use `--trust`. Bootstrap is also versioned. New CDK features occasionally require a newer bootstrap stack; the CLI compares the SSM version parameter against what the synthesized app requires and tells you to re-bootstrap. Re-running is idempotent — it is a CloudFormation stack update like any other: ```bash cdk bootstrap aws://123456789012/eu-west-1 \ --trust 555555555555 \ --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess ``` ## Operational consequences The staging bucket is a real, growing resource; assets accumulate across deployments and nothing removes them automatically by default. Deleting the `CDKToolkit` stack, or emptying the bucket, breaks deploys and can break rollbacks that still reference old assets — treat it as production infrastructure, not scratch space. And because bootstrap is a privileged, one-time action, it usually belongs with the team that owns account provisioning rather than in each app's pipeline.

  • Why does the bootstrap create a separate CloudFormation execution role instead of letting the deploying identity create resources directly?
    It separates who may start a deployment from what a deployment may do. Developers and CI only need permission to assume the deploy and publishing roles; the broad create and delete permissions sit on the execution role, which only CloudFormation assumes. You set its policies at bootstrap time with `--cloudformation-execution-policies`, so the blast radius of the whole pipeline is narrowed in one place.
  • What is the qualifier for, and what happens if the app and the bootstrap disagree on it?
    The qualifier is the short string embedded in every bootstrapped resource name so multiple independent bootstraps can coexist in one account. If your app synthesizes with a different qualifier than the one you bootstrapped, it emits references to a bucket and roles that do not exist, and the deploy fails on a missing resource or an assume-role error rather than anything obviously bootstrap-shaped.
  • A pipeline in a tooling account must deploy into production. What has to happen in the production account?
    Production must be bootstrapped with `--trust <tooling-account>` and an explicit `--cloudformation-execution-policies`. That lets roles from the tooling account assume production's deploy and publishing roles. Without it the pipeline can synthesize fine and still fail at publish time, because nothing in production will let it in.

saying these in an interview costs you the question

  • Thinks one bootstrap per account covers every region
  • Believes bootstrap deploys the application stacks
  • Assumes bootstrap is only needed when the app uses assets
  • Treats the CDKToolkit stack as disposable scratch infrastructure
  • Says cross-account deploys work without a trust relationship

context