cdkd Architecture Documentation
cdkd deploys a CDK app without CloudFormation. It runs the app to get a CloudFormation template, works out what changed since the last deploy, and calls AWS APIs directly to create, update and delete resources.
This page gives you the model to hold in your head before you change the
source: the seven layers, and what one cdkd deploy does from start to finish.
Each part has its own page with the detail.
In this section
- The deploy pipeline follows a deploy through synthesis, asset publishing, the diff and the resource operations.
- Destroy, state and locking covers what
cdkd destroydoes, where state is stored, and how a stack is locked. - Providers and intrinsic functions covers how
a resource operation reaches AWS, and how
Refand theFn::functions are turned into values. - Architecture internals holds the detailed rules behind the diff, secrets in state and asset storage. Read it when you change one of those modules.
The seven layers
The source is organised as seven layers. Each layer is one directory under
src/, does one job, and hands its result to the next layer.
| Layer | Directory | Owns |
|---|---|---|
| CLI | src/cli/ |
Commands, option parsing, config resolution |
| Synthesis | src/synthesis/ |
Running the CDK app, reading its output, context lookups |
| Assets | src/assets/ |
Uploading files to S3, pushing images to ECR |
| Analysis | src/analyzer/ |
Template parsing, the dependency graph, the diff |
| State | src/state/ |
The state file in S3, the stack lock |
| Deployment | src/deployment/ |
Ordering and running resource operations, intrinsic resolution, rollback |
| Provisioning | src/provisioning/ |
The AWS calls: SDK providers, with Cloud Control as the fallback |
The diagram shows the same layers with the main files in each:
Three directories sit beside the layers. Shared types are in src/types/,
shared helpers are in src/utils/, and the local emulation commands
(cdkd local ...) are in src/local/.
What cdkd deploy does
cdkd deploy MyStack
Suppose MyStack contains a Lambda function and an SQS queue. The command goes
through five stages, and each stage belongs to one or two layers:
- Resolve the configuration. The CLI works out which command runs the CDK app and which S3 bucket holds cdkd's state.
- Synthesize. cdkd runs the CDK app as a subprocess. The app writes a directory called the cloud assembly, which holds one CloudFormation template and one list of assets for each stack.
- Schedule. Every asset and every stack becomes a node in one graph of work, so that a stack starts only after its assets are published.
- Publish the assets. The function's code is uploaded to S3. A Docker image would be pushed to ECR. An asset that is already there is skipped.
- Deploy the stack. cdkd locks the stack, loads its state, and compares the template with the state. It then runs the changes in dependency order, saves the state, and releases the lock.
On the first deploy there is no state, so the comparison marks the function and the queue as resources to create. On a later deploy the state records what the last deploy created, and a resource that the comparison finds unchanged is left alone.
The last step of the diagram splits in two because cdkd has two ways to call AWS. A resource type with a hand-written SDK provider is created through that service's own API. Any other type goes through the Cloud Control API. Providers and intrinsic functions explains how the choice is made.
The deploy pipeline describes each of the five stages in detail.
What cdkd destroy does
cdkd destroy MyStack does not run the diff, because it does not need the
template. It reads the stack's state, works out the order from the
dependencies recorded there, and deletes every resource in reverse dependency
order. Destroy, state and locking has the
steps.
Where things live
Use this table to get from a task to the file you start in.
| To change | Start in |
|---|---|
| A command or a flag | src/cli/commands/<command>.ts, src/cli/options.ts |
How --app or --state-bucket is resolved |
src/cli/config-loader.ts |
| How the CDK app is run | src/synthesis/app-executor.ts |
| A context lookup | src/synthesis/context-providers/ |
| Asset upload or image push | src/assets/file-asset-publisher.ts, src/assets/docker-asset-publisher.ts |
| Dependency edges | src/analyzer/dag-builder.ts |
| What counts as a change, or as a replacement | src/analyzer/diff-calculator.ts, src/analyzer/replacement-rules.ts |
| Drift detection | src/analyzer/drift-calculator.ts |
| The state file's shape | src/types/state.ts, src/state/s3-state-backend.ts |
| Locking | src/state/lock-manager.ts |
| The order resources run in | src/deployment/dag-executor.ts |
| What a deploy does to one resource | src/deployment/deploy-engine/ |
| Rollback | src/deployment/rollback-executor.ts |
| How an intrinsic resolves | src/deployment/intrinsic-resolver/ |
| Which provider handles a type | src/provisioning/provider-registry.ts, src/provisioning/register-providers.ts |
| One resource type's AWS calls | src/provisioning/providers/ |
| Logging, AWS clients, error classes | src/utils/logger.ts, src/utils/aws-clients.ts, src/utils/error-handler.ts |
The CLI entry point is src/cli/index.ts.
Design constraints
Five constraints hold across the codebase. A change that breaks one of them needs a reason.
- Each layer does one job. The CLI parses and prints, analysis plans, deployment orders the work, and provisioning calls AWS.
- The engine depends on the
ResourceProviderinterface. The engine never names a concrete provider, so supporting a new resource type means registering a provider. - No
@aws-cdk/*imports. Synthesis, reading the cloud assembly and publishing assets are implemented in this repository.aws-cdk-libis the user's dependency, and it is adevDependencyhere for the tests. - State follows AWS. State is saved as each resource completes, so a failed or interrupted run can be rolled back, resumed or destroyed.
- The common path stays fast. A check added to deploy or destroy must not grow with the number of stacks or resources.
What limits deploy speed
Four things limit how fast a deploy can be:
- Asset publishing, which uploads Lambda code and pushes images.
- Cloud Control polling, for resource types that have no SDK provider.
- Cloud Control rate limits, which apply per resource type.
- Long dependency chains, which cap how much can run in parallel.
Measured comparisons with CloudFormation are in Benchmarks.
What cdkd does not do
- cdkd has no change sets. A deploy applies its changes. To preview them, run
cdkd difforcdkd deploy --dry-run. - A CloudFormation macro whose output contains another macro is not supported. A single-stage macro is expanded through a temporary CloudFormation change set.