cdkd Is More Than Blazing-Fast CDK Deploys: Trying Out Every Command
cdkd is an open-source CLI that deploys your existing AWS CDK code up to 15x faster by calling the AWS SDK and Cloud Control API directly. But speed isn't all it offers. This post walks through its commands, from running Lambda and API Gateway locally to fixing drift, removing deletion protection, and moving stacks to and from CloudFormation.
AI writes the code in seconds, and we still wait minutes to deploy it
Hi! I'm Hayakawa, and I love AWS CDK!
Coding agents now write pretty good CDK code, so for small setups I hardly write CDK code by hand anymore.
But even if the code takes no time to write,
cdk deploy still makes you wait several minutes, just like before.cdkd (CDK Direct), an open-source tool by AWS Hero Goto-san (go-to-k ), solves this problem.
It is a CLI that speeds up deployment of your existing code: just replace
It is a CLI that speeds up deployment of your existing code: just replace
cdk deploy with cdkd deploy, and you get deploys up to 15 times faster!It was also presented at AWS CDK Conference Japan 2026 , which I attended, and I had been curious about it ever since.
Reading the README, I found that cdkd comes with a lot of commands.
In this post, I'll walk through cdkd's commands along with when to use them!
In this post, I'll walk through cdkd's commands along with when to use them!
※ This post is based on the main branch (v0.284.x) as of August 2026. As the documentation states, cdkd is not recommended for production use.
Getting started with cdkd
cdk deploy works in two steps:- Synthesize a CloudFormation template from your CDK code
- Hand the template to CloudFormation and let it deploy
cdkd replaces the second step.
Instead of going through CloudFormation, it calls the AWS SDK and the Cloud Control API directly.
That's why it's fast!
Instead of going through CloudFormation, it calls the AWS SDK and the Cloud Control API directly.
That's why it's fast!
Since there is no CloudFormation stack, cdkd keeps the stack state, which CloudFormation used to hold, in an S3 bucket.
1
2
npm i -g @go-to-k/cdkd
cdkd bootstrap # Replaces cdk bootstrap; run once per account. Creates the S3 bucket (and more) that holds stack stateAfter that, you just replace
cdk with cdkd. You don't touch your CDK code, so you keep developing with CDK the same way as before.1
2
cdkd deploy # replaces cdk deploy
cdkd destroy # replaces cdk destroyIn his introduction article (in Japanese), Goto-san himself writes that cdkd "complements the AWS CDK CLI rather than replacing it."
A good approach seems to be deploying quickly with cdkd during development and leaving production to the official CDK CLI.
A good approach seems to be deploying quickly with cdkd during development and leaving production to the official CDK CLI.
Everyday commands (synth / deploy / diff / destroy)
The everyday commands are almost the same as in the official CDK CLI, so there's nothing new to learn.
1
2
3
4
5
6
7
cdkd synth
cdkd deploy # picked automatically if there is only one stack
cdkd deploy MyStack
cdkd deploy --all
cdkd deploy --dry-run # show the plan without changing anything
cdkd diff MyStack --fail # exit code 1 if there are differences
cdkd destroy MyStackIf a deployment fails partway through, cdkd rolls back the resources it created or modified, just like the official CDK CLI.
Note, however, that its behavior and guarantees are not necessarily identical to CloudFormation's rollback.
Note, however, that its behavior and guarantees are not necessarily identical to CloudFormation's rollback.
With
If you want to roll back later, there is also
--no-rollback, cdkd skips the rollback and leaves the intermediate state in place.
If you want to roll back later, there is also
cdkd rollback.I tried it on a small stack with just DynamoDB, Lambda, and API Gateway, and the first deployment finished in 29.22 seconds.
1
2
3
4
5
6
Deploying 16 resource(s) (DAG: 7 levels, max parallel: 10)
[1/16] ✓ ApiF70053CD (AWS::ApiGateway::RestApi) created
[2/16] ✓ HandlerServiceRoleFCDC14AE (AWS::IAM::Role) created
IAM propagation delay for ApiAccountA18C9B29 (attempt 1/3), retrying in 10s...
...
Duration: 29.22scdkd expands the resource dependencies into a directed acyclic graph (DAG) with 7 levels and runs up to 10 operations in parallel.
When IAM propagation hadn't caught up yet, it retried instead of failing.
When IAM propagation hadn't caught up yet, it retried instead of failing.
Choose how long to wait (--no-wait / --full-wait)
cdk deploy is slow because, after asking AWS to create a resource, CloudFormation waits until it can confirm that the resource is ready to use.
cdkd waits only when something else in the same deployment needs that state, or when waiting lets it detect a failure.
For example, a CloudFront distribution takes 3 to 15 minutes to propagate to the edge after creation.
But nothing in the same deployment needs that propagation to finish, so by default cdkd moves on as soon as
But nothing in the same deployment needs that propagation to finish, so by default cdkd moves on as soon as
CreateDistribution is accepted.The following two options change this behavior.
| Option | Applies to | Behavior |
|---|---|---|
--no-wait | RDS, ElastiCache, NAT Gateway, EC2 instances, ELBv2 load balancers, Lambda MicroVM Image | Waits by default; with this option, moves on as soon as the create API returns |
--full-wait | ECS services, CloudFront distributions | Doesn't wait by default; with this option, waits until ECS tasks are stable and until CloudFront has finished propagating |
Note that
According to the README, it isn't available for destroy because a NAT Gateway that is still being deleted holds on to its ENI, and deleting other resources then fails with
--no-wait is deploy-only.
According to the README, it isn't available for destroy because a NAT Gateway that is still being deleted holds on to its ENI, and deleting other resources then fails with
DependencyViolation.Run without deploying (cdkd local)
Roughly speaking,
cdkd local is like sam local: it runs everything from Lambda, API Gateway, ECS, ALB, and CloudFront to Bedrock AgentCore Runtime locally.1
2
cdkd local invoke MyStack/Handler
cdkd local start-api MyStack/MyApi --watchA common source of errors in local runs is environment variables that reference other resources.
For example, if a Lambda function reads from a DynamoDB table, CDK passes the table name in an environment variable such as
But the table name isn't decided until deployment.
The template CDK synthesizes contains only a placeholder (
TABLE_NAME.
But the table name isn't decided until deployment.
The template CDK synthesizes contains only a placeholder (
Ref) meaning "fill in the actual name later," so running locally alone can't resolve it.cdkd solves this by replacing
Which flag to use depends on whether you deployed the stack with cdk or with cdkd.
Ref and Fn::ImportValue in environment variables, secrets, and image URIs with the actual values from the deployed stack.
Which flag to use depends on whether you deployed the stack with cdk or with cdkd.
| How the stack was deployed | Flag | Where values come from |
|---|---|---|
cdk deploy (managed by CloudFormation) | --from-cfn-stack | CloudFormation stack |
cdkd deploy (managed by cdkd) | --from-state | cdkd state (S3) |
1
cdkd local start-api MyStack/MyApi --from-cfn-stackWithout either flag, cdkd only prints a warning and doesn't pass that environment variable.
Here's what happened when I deployed the setup above with cdkd and tried it without a flag.
Here's what happened when I deployed the setup above with cdkd and tried it without a flag.
1
2
3
4
Environment variable TABLE_NAME contains a CloudFormation intrinsic and was dropped.
Override it with --env-vars ..., or pass --from-state / --from-cfn-stack to recover deployed values.
{"message":"hello from cdkd","tableName":null,"stage":"dev"}Adding
--from-state puts the actual table name into tableName.1
{"message":"hello from cdkd","tableName":"CdkdDemoApi-Items5C12978B","stage":"dev"}start-api reads from the CDK app which path routes to which Lambda function, and starts a local HTTP server as is.1
2
3
4
ApiF70053CD (REST API v1) (http://127.0.0.1:39073)
Discovered routes:
ANY / -> Handler886CB40B (REST v1, stage 'prod')
ANY /{proxy+} -> Handler886CB40B (REST v1, stage 'prod')In other words, you can keep deploying with
cdk deploy and install cdkd just for local runs.With
local start-cloudfront, if you only use CloudFront Functions and an S3 origin, you don't even need Docker, and you can check changes to your routing function in seconds.Find and fix drift (cdkd drift)
CloudFormation drift detection only looks at the properties written in the template.
cdkd is different: it records the state on the AWS side at deployment time and compares it with the current state, so changes made in the console to settings not in the template also show up as differences.
cdkd is different: it records the state on the AWS side at deployment time and compares it with the current state, so changes made in the console to settings not in the template also show up as differences.
1
2
3
4
cdkd drift MyStack # exit code 1 if there are differences
cdkd drift MyStack --accept --yes # state ← AWS (treat the console changes as correct)
cdkd drift MyStack --revert --yes # AWS ← state (undo the console changes)
cdkd drift MyStack --json # output in a format CI can readWith
--dry-run, you can check the planned resolution without changing the state or the AWS resources.Delete and clean up (destroy / orphan / gc)
destroy deletes both the AWS resources and their records in the state, while orphan deletes only the state records and leaves the AWS resources in place.1
2
cdkd destroy MyStack
cdkd orphan MyStack/MyBucket # remove just one resource from the stateRemove deletion protection in one go (--remove-protection)
This happens all the time in test environments: if RDS or DynamoDB has deletion protection enabled, destroy stops with an AWS error.
It doesn't delete everything else and leave just the protected resources; it fails right there.
You end up disabling the protection in the console and running destroy again.
It doesn't delete everything else and leave just the protected resources; it fails right there.
You end up disabling the protection in the console and running destroy again.
1
cdkd destroy MyStack --remove-protectioncdkd disables deletion protection right before deleting each resource, so you don't have to fix your CDK code and redeploy.
Since this is a fairly dangerous option, cdkd thoughtfully changes the confirmation prompt's default from
Y/n to y/N.There is also
The CDK L2 construct for RDS defaults to
--skip-final-snapshot.
The CDK L2 construct for RDS defaults to
SNAPSHOT, so in a test environment this makes destroy several minutes faster.Clean up accumulated assets (cdkd gc)
cdkd destroy doesn't empty the S3 bucket and ECR repository for assets that cdkd bootstrap created.
cdkd gc is the command that deletes them.1
2
cdkd gc --older-than 30d --dry-run # list unreferenced assets older than 30 days without deleting them
cdkd gc --older-than 30d # actually delete themgc aborts if even one stack is being deployed, so run it when no deployments are in progress.
View state without a CDK app (cdkd state)
All the commands so far assume you have the CDK source code at hand, but the
They come in handy when you don't have the source, or when you don't want to spend time on synth.
cdkd state commands are the exception: they look only at the state bucket in S3.
They come in handy when you don't have the source, or when you don't want to spend time on synth.
1
2
3
4
5
6
7
cdkd state info # bucket name, region, schema version
cdkd state list # list of stacks and regions
cdkd state list --tree # parent-child tree of nested stacks
cdkd state show MyStack # contents of the state
cdkd state resources MyStack # logical ID, type, physical ID
cdkd state destroy MyStack # delete the stack including its resources, without a CDK app
cdkd state orphan MyStack # delete only the state recordsMoving back and forth with CloudFormation (import / export)
Even a stack already built with
cdk deploy can be taken out of CloudFormation's management and moved under cdkd's management, without affecting the AWS resources.You use
cdkd import for this.1
cdkd import MyStack --migrate-from-cloudformation --yescdkd reads the mapping between logical IDs and physical IDs from the original CloudFormation stack and imports all resources into the cdkd state.
It then sets
Now you can use
It then sets
Retain on every resource and deletes the original stack.
Now you can use
cdkd deploy.Now suppose you want to move the stack back under CloudFormation's management.
Running
The original stack is already gone, so CloudFormation would try to create everything from scratch as a new stack.
This is where
cdk deploy won't bring it back.
The original stack is already gone, so CloudFormation would try to create everything from scratch as a new stack.
This is where
cdkd export comes in.1
2
cdkd export MyStack --dry-run # just check what would happen
cdkd export MyStackIt uses a change set with
On success, the cdkd state is deleted, and you can go back to operating the stack with
ChangeSetType=IMPORT to bring the existing resources back under CloudFormation's management as is.
On success, the cdkd state is deleted, and you can go back to operating the stack with
cdk deploy.Things to keep in mind when using cdkd
| Point | Details |
|---|---|
| Not recommended for production | The documentation clearly states that cdkd is meant for development and testing. |
| IAM permissions | The IAM user or role that runs cdkd needs permissions to operate the target AWS services directly. If you plan to keep using it, design least-privilege permissions scoped to the target resources, regions, and actions. |
| Unsupported resources | AWS resources not supported by an SDK Provider or the Cloud Control API can't be deployed. That said, since everything starts from CDK source code, this may rarely come up in practice... |
Summary
In an era when AI lets us write CDK code at high speed, along comes a high-speed deployment tool: cdkd.
Looking into its commands one by one, I found it's much more than just a fast tool.
Here are the commands covered in this post.
Looking into its commands one by one, I found it's much more than just a fast tool.
Here are the commands covered in this post.
| What you want to do | Command |
|---|---|
| Deploy faster | cdkd deploy (change how long it waits with --no-wait / --full-wait) |
| Check the diff first | cdkd diff --fail / cdkd deploy --dry-run |
| Run locally without deploying | cdkd local invoke / start-api (--from-cfn-stack / --from-state) |
| Find and fix drift | cdkd drift (--accept / --revert) |
| Delete even with deletion protection | cdkd destroy --remove-protection |
| Delete accumulated assets | cdkd gc |
| View state without the source | cdkd state list / show / resources |
| Move back and forth with CloudFormation | cdkd import --migrate-from-cloudformation / cdkd export |
It's a tool that only an author who knows CDK development inside out could build.
I can't wait to see how its supported resources and operational features grow from here!
I can't wait to see how its supported resources and operational features grow from here!
References
| Link | Description |
|---|---|
| cdkd GitHub repository | The cdkd repository. The README was extremely helpful |
| I built cdkd, which deploys up to 15x faster with your existing AWS CDK code | Introduction article by the author (in Japanese) |
| I built AWS CDK from scratch: what I learned about CDK's internals | Slides from AWS CDK Conference Japan 2026 (in Japanese) |
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article