A tool claiming "up to 15x faster than cdk deploy" showed up in my feed a while back. Drop-in replacement, it said: keep your CDK app exactly as it is, just swap cdk deploy for cdkd deploy.
I've learned to be skeptical of "Nx faster" claims. So I actually deployed something real to AWS with both tools and timed it. Short version: it really is that fast.
What cdkd actually is
cdkd deploys an existing AWS CDK app without going through CloudFormation. It calls the AWS SDK directly instead. It's built by go-to-k (Kenta Goto), an AWS DevTools Hero and CDK top contributor who also maintains cls3 (a fast S3 bucket emptier) and delstack (for cleaning up stuck CloudFormation/CDK stacks) — tools that quietly fix the annoying parts of working with AWS. cdkd feels like the biggest one yet, and I mean that as a compliment grounded in actually using it, not a throwaway one.
The mechanism is straightforward. cdkd runs the exact same CDK synth step as the CDK CLI, producing the same CloudFormation template. What changes is everything after that: instead of handing the template to CloudFormation, cdkd's own engine reads the resource dependency graph (Ref, Fn::GetAtt), builds a DAG, and fires AWS SDK / Cloud Control API calls directly, in parallel, as soon as each resource's dependencies are satisfied.
Worth saying up front: cdkd calls itself not production-ready, dev/test only. This isn't a "replace CloudFormation in prod" pitch.
I actually ran both, on real AWS
cdkd's own README backs up the 15x number with a VPC + Lambda + SQS + CloudFront benchmark. So I wrote that same stack as a CDK app and deployed it twice — DeployRaceCfn via cdk deploy, DeployRaceCdkd via cdkd deploy — to the same AWS account, same region (ap-northeast-1).
The stack:
- VPC (2 AZ + NAT Gateway) with a Lambda inside it, fronted by a Function URL
- CloudFront, origin set to that Function URL
- SQS + EventSourceMapping + a consumer Lambda
First attempt failed. The account had hit its VPC limit (five, the default):
Resource handler returned message: "The maximum number of VPCs has been reached.
(Service: Ec2, Status Code: 400, ...)"
Other test stacks in the same account were sitting on VPCs I'd forgotten about. I tore down the cdkd stack (already measured, no longer needed) to free a slot and reran. cdkd writes a structured event log to S3 on every run (cdkd events), so even the failed attempt was easy to diagnose after the fact.
Timing compares the deploy phase only. Synth is identical work either way (same aws-cdk-lib), so I excluded it, matching how cdkd's own benchmarks are measured. The cdk deploy timeline comes from CloudFormation's DescribeStackEvents; the cdkd deploy timeline comes from cdkd events <stack> --run <id> --format json, reading the RESOURCE_STARTED / RESOURCE_SUCCEEDED events it records itself.
The numbers
| cdk deploy | cdkd deploy | |
|---|---|---|
| Time | 479.3s | 95.0s |
| Resources created | 34 | 33 |
5.0x. The one extra resource on the CloudFormation side is AWS::CDK::Metadata, a bookkeeping resource that only exists there — both sides build the same 33 real resources.
Watching cdkd deploy run, IAM roles and route tables land in a burst right at the start:
[1/33] ✓ RaceQueueE818AC65 (AWS::SQS::Queue) created
[2/33] ✓ RaceVpcIGW94C1C01D (AWS::EC2::InternetGateway) created
[3/33] ✓ RaceVpcPublicSubnet1EIPC3B3497E (AWS::EC2::EIP) created
[4/33] ✓ ConsumerFunctionServiceRole68E8FEB1 (AWS::IAM::Role) created
[5/33] ✓ MainFunctionServiceRole8C918DF0 (AWS::IAM::Role) created
...
CloudFront Distribution Distribution830FAC52 accepted (not waiting for Deployed; pass --full-wait to wait)
Deployment Summary:
Created: 33 / Duration: 94.99s
Meanwhile cdk deploy takes 16.6 seconds just to get its first VPC. By that point cdkd already has the Lambda wired up to SQS.
Where the time actually goes
cdk deploy hands the template to CloudFormation, which creates resources one at a time. cdkd reads the same template's dependency graph itself and calls the AWS SDK / Cloud Control API directly, in parallel, as soon as dependencies clear. Cutting out the CloudFormation middleman is most of the story, but two specific waits explain most of the 384-second gap.
The NAT Gateway is the first one. cdk deploy works through the SQS/Lambda side of the graph before it gets around to waiting on the NAT Gateway to come up. cdkd hits that wait much earlier. Same AWS-side wait either way — what differs is how early in the run you eat it.
CloudFront is the bigger one. CloudFormation's default behavior waits until the distribution reaches Deployed — full global propagation, three-plus minutes. cdkd's default returns as soon as CreateDistribution is accepted (there's a --full-wait flag if you want CloudFormation's behavior instead). Of the 479.3 seconds cdk deploy took, 183 of them — over three minutes — are spent solely on that one wait.
This might actually change how people deploy
I'll admit it: the slowness of iterating on a real AWS resource is part of why people reach for Vercel or Amplify instead. Build a VPC + Lambda + CloudFront stack in CDK and every check-your-work loop costs minutes, sometimes double digits of them.
cdkd doesn't replace CloudFormation's state management, drift detection, or rollback handling, and it says so itself. But "CloudFormation in prod, cdkd while iterating" is now a real option, not a hypothetical. A CI pipeline that rebuilds a PR environment on every push, or just the apply-then-check loop on your own machine, running five times faster is enough to make "AWS-native is slower to iterate on than Vercel or Amplify" stop being true for a chunk of use cases.
I also built an interactive replay of the actual measured timeline, plus a narrated demo video, if you want to see the two runs side by side.
cdkd is go-to-k/cdkd (Apache-2.0). Worth a star if this was useful.


Top comments (0)