Somewhere on Reddit or AWS re:Post right now, someone is asking a version of the same question: is CloudFormation dead now that CDK exists? It's not a rhetorical question. Teams are picking one of these tools for a project that will outlive whoever chose it, and most comparison articles answer with a feature table instead of a verdict.
I've deployed production stacks with both tools across client engagements, and the honest answer is more useful than a table: no, CloudFormation isn't dead, and the reasons engineers give for skipping CDK are real but fixable. If you want the ground-level AWS CDK fundamentals first, start there and come back. Below: the mechanics underneath both tools, the objections practitioners actually raise about CDK (the bootstrap tax, the feature lag, the portability trap, the maintainability complaint), what changed in both tools over the last eighteen months, and the heuristic that holds up once you've shipped both approaches in production.
Is CloudFormation Deprecated Now That CDK Exists?
No. CDK doesn't replace CloudFormation, it authors it. Every cdk deploy synthesizes your application into one or more CloudFormation templates, hands them to the CloudFormation service, and lets CloudFormation create and execute a change set. There is no separate CDK deployment engine and no separate state store: every CDK-managed resource lives inside CloudFormation's own state model, with the same stack statuses, the same rollback behavior, and the same drift detection a hand-written template gets.
AWS's own community forum, re:Post, has fielded a version of this question for years, and the consistent answer from AWS engineers runs the opposite direction of "deprecated": CDK makes CloudFormation more central to how you deploy on AWS, not less. Adopting CDK doesn't reduce your dependency on CloudFormation, it adds a code-generation layer in front of it. If CloudFormation actually went away, CDK would have nothing left to deploy through.
That distinction matters for how you should read the rest of this article. Every objection engineers raise about CDK is a question about a thin authoring layer over a service you're already using, or would be using anyway if you wrote templates by hand. None of it is a referendum on whether CloudFormation itself is going anywhere.
To see why that's true mechanically, not just definitionally, look at what actually happens when you run cdk deploy.
What Actually Happens When You Run cdk deploy
CDK's deployment pipeline has five steps, and they explain almost every objection covered later.
1. Synthesis. cdk synth compiles your CDK app into a cloud assembly, a directory (cdk.out by default) containing a CloudFormation template per stack, plus assets like Lambda code and Docker images, plus deployment metadata. This step runs on your machine and touches no AWS API, unless the stack uses environment lookups like Vpc.fromLookup, which query AWS during synthesis and cache the answer in cdk.context.json.
2. Asset publishing. Before deployment, cdk deploy uploads file and Docker assets referenced in the synthesized template to the bootstrap S3 bucket and ECR repository (more on what that bootstrap step provisions in the next section).
3. Change set creation. Under the default --method=change-set, CDK creates a CloudFormation change set from the synthesized template, the same "preview before apply" primitive available to anyone deploying CloudFormation by hand. --method=direct skips the change set and applies the update immediately, which is faster but costs you the preview and the progress detail; prepare-change-set and execute-change-set split the halves apart for approval workflows. All four deploy through CloudFormation.
4. Execution. CloudFormation runs the change set: CREATE, UPDATE, and DELETE operations on resources, identical to what happens if you'd created that change set yourself in the console.
5. The hotswap shortcut, optional. cdk deploy --hotswap bypasses CloudFormation altogether, updating supported resources through service APIs (Lambda code and config, Step Functions definitions, ECS container images) for faster iteration. It also disables rollback and deliberately introduces stack drift. AWS is direct about the trade-off: hot-swapping is not recommended for production deployments.
The diagram below shows these paths and why they carry different risk profiles.
cdk diff makes the change-set relationship explicit rather than hiding it. Run it against a stack and the CLI prints exactly what it's doing: "Hold on while we create a read-only change set to get a diff with accurate replacement information (use --method=template to use a less accurate but faster template-only diff)." In its default auto mode, cdk diff is a CloudFormation change set rather than a separate diff engine, though it quietly falls back to a template-only comparison when the change set can't be created, typically for want of permissions. Worth knowing, because the fallback is less accurate about replacements than the output you were expecting.
You can see the same relationship in a synthesized template. A small CDK construct:
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cdk from 'aws-cdk-lib';
new s3.Bucket(this, 'ReportsBucket', {
versioned: true,
removalPolicy: cdk.RemovalPolicy.RETAIN,
});
produces this CloudFormation, trimmed to the resource that matters:
Resources:
ReportsBucket4EB968BC:
Type: AWS::S3::Bucket
Properties:
VersioningConfiguration:
Status: Enabled
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
Metadata:
aws:cdk:path: MyStack/ReportsBucket/Resource
Notice RemovalPolicy.RETAIN didn't invent new CloudFormation behavior. It set two native attributes, DeletionPolicy and UpdateReplacePolicy, that a hand-written template would set the same way. That pattern, a CDK convenience wrapping a plain CloudFormation attribute, repeats throughout the construct library. Once you internalize it, "what does this CDK feature actually do" almost always has a one-line CloudFormation answer.
That mechanism explains the first thing practitioners bring up when they argue for staying on plain CloudFormation: what CDK asks you to set up before any of this can run.
The Bootstrap Tax: What CDK Requires That Plain CloudFormation Doesn't
The most common practical argument for CloudFormation is some version of "the only real benefit is one-click deployment, no setup." That's not quite right, but it points at something real: CDK requires a one-time environment setup hand-written CloudFormation skips entirely.
Run cdk bootstrap and CDK deploys a stack, named CDKToolkit by default, into the target account and Region. It provisions an S3 bucket for assets, an ECR repository for Docker images, and five IAM roles:
| Role | Purpose |
|---|---|
CloudFormationExecutionRole | The service role CloudFormation itself assumes to perform stack deployments on your behalf |
DeploymentActionRole | Assumed by the CDK CLI to perform deployments; enables cross-account deploys |
FilePublishingRole | Assumed by the CDK CLI to read/write the bootstrap S3 bucket |
ImagePublishingRole | Assumed by the CDK CLI to read/write the bootstrap ECR repository |
LookupRole | Read-only role the CDK CLI uses during synthesis to look up context values (existing VPCs, hosted zones, and similar) |
Plain CloudFormation deployments that don't reference local file assets skip all of this. There's nothing to stage before the CreateStack call, so there's no need for a staging bucket, a container registry, or roles dedicated to writing to them. Deployment authorization is whatever IAM credentials or execution role you already configured, without a shared, persistent toolkit stack sitting in the account.
The security framing matters more than the setup friction. AWS's bootstrapping documentation is candid that the deployment role "is effectively an administrator," since its CloudFormation execution permissions reach almost anything regardless of narrower IAM restrictions layered on top. And AWS is equally direct about the blast radius of losing it: "If a bootstrap stack is deleted, the AWS resources that were originally provisioned in the environment to support CDK deployments will also be deleted... there is no general solution for recovery." That's why AWS recommends --termination-protection on the bootstrap stack: you're introducing a Tier-0 asset into every account you bootstrap, one that plain CloudFormation deployments never create.
If you're setting up bootstrap for the first time, our full walkthrough of what cdk bootstrap creates covers the customization options and common failure modes. And if the objection you're actually weighing is console-first deployment against CDK's toolchain, deploying a template straight from the CloudFormation console is the direct comparison point.
Bootstrapping is a setup tax rather than a per-deployment one: you pay it once per account and Region, then re-run it when the bootstrap template version moves, when you add cross-account trust, or when you upgrade across major CDK versions.
When CloudFormation Gets a New Feature Before CDK Does
This complaint is still partly true, and worth stating plainly instead of hand-waving: CDK's higher-level constructs can lag behind what CloudFormation itself supports on day one. But the shape of the lag is narrower than most engineers assume, and CDK ships a fix that takes minutes, not a framework migration.
CDK's construct library has three abstraction levels. L1 constructs (the Cfn* classes, like CfnBucket) are a direct, code-generated mapping to every CloudFormation resource type and property. Because L1s are generated straight from the CloudFormation resource specification, anything expressible in raw CloudFormation becomes expressible through an L1 as soon as those generated classes ship, typically within about a week of release. L2 constructs (like Bucket) are the curated layer with sensible defaults, and this is where lag bites: a new service or a new property on an existing resource might not get L2 ergonomics for weeks or months. L3 constructs compose multiple resources into a pattern.
The gap only bites if you assume L2 is your only option. It isn't. When an L2 construct doesn't expose a property you need, addPropertyOverride closes the gap without waiting for a library release:
const cfnBucket = bucket.node.defaultChild as s3.CfnBucket;
cfnBucket.addPropertyOverride('ObjectLockEnabled', true);
You get the L1 resource underneath the L2 construct via .node.defaultChild, then set whatever CloudFormation property the L2 API hasn't surfaced yet. It's a decision criterion you can apply immediately: if the L2 construct's TypeScript types don't expose the property, drop to addPropertyOverride instead of waiting for a new construct-library release.
For wholesale gaps, CfnInclude imports an entire hand-written CloudFormation template into a CDK app as first-class L1 resources you can then extend with CDK code. Keep it distinct from the other migration path: CfnInclude is stable and production-ready, while cdk migrate, which generates a brand-new CDK app from a deployed stack, a local template, or a live-resource scan, is explicitly labeled experimental by AWS and may have breaking changes. Reach for CfnInclude to bring existing CloudFormation into CDK today; treat cdk migrate as a tool you test before you trust it in a pipeline. For what each construct level buys you, see our guide to CDK constructs, and for overrides against a resource type you don't have memorized, our CloudFormation resource properties reference beats digging through the CDK API docs mid-override.
Feature lag is annoying but fixable in an afternoon. The next objection is harder to walk back once it ships.
Does CDK Make Your Templates Less Portable? The Hardcoding Objection
This is the most sophisticated objection engineers raise, and it's the one fewest comparison articles touch: does CDK's programming-language ergonomics make it easy to bake account- and Region-specific values into construct logic where a hand-written CloudFormation template would have forced a Parameter, a Mapping, or a Condition?
The objection is fair, and AWS's own guidance takes a clear position on it rather than staying neutral. On the "Parameters and the AWS CDK" page, AWS states it directly: "In general, we recommend against using AWS CloudFormation parameters with the AWS CDK." The reasoning is that parameter values aren't available at synthesis time, so they can't drive flow control in your CDK app the way a native if statement can. AWS's stated ideal: "An ideal AWS CDK-generated AWS CloudFormation template is concrete, with no values remaining to be specified at deployment time." The CDK Best Practices guide extends the same logic to Conditions and Fn::If, favoring your language's native if statements at synthesis time instead.
So what replaces Parameters and Conditions in CDK? AWS's "Environments for the AWS CDK" guide gives a direct recommendation: hard-code the env property (literal account and Region strings) for production stacks, and use the CDK_DEFAULT_ACCOUNT / CDK_DEFAULT_REGION environment variables (sourced from your active CLI credentials) for development stacks. That's the opposite of what "hardcoding" usually implies as a criticism: AWS's own production recommendation is a literal, explicit environment value.
The trap isn't the literal value, it's skipping the env property entirely and relying on whatever CLI profile happens to be active. Omit env and CDK produces an environment-agnostic template. That sounds portable, and it is, at a cost: environment-agnostic stacks can't use environment information in code (no if (stack.region === 'us-east-1'), no Vpc.fromLookup), and AWS's docs note an easy-to-miss consequence: any construct using Availability Zones sees exactly two, a fixed default chosen so the stack can synthesize without knowing the real target Region.
The decision criterion: if you'd reach for a CloudFormation Parameter or Mapping to make a template reusable across environments, reach for CDK's env property (literal for production, CDK_DEFAULT_* for development) and context values instead, and keep environment-specific decisions in your programming language. Commit cdk.context.json once you start using lookups like Vpc.fromLookup, since that's where CDK caches the non-deterministic values those lookups resolve, and an uncommitted context file is how a stack that worked last month quietly resolves differently in CI.
Portability is a code-authoring discipline problem, and AWS's own docs hand you the discipline to fix it in code.
CDK Is Great Until You Inherit Someone Else's CDK Code
This one is mostly fair, and mostly not a CDK problem. The same construct-level abstraction that makes good CDK code powerful, hiding CloudFormation boilerplate behind a class, makes bad CDK code opaque. A construct that quietly does five things across three resources is exactly as hard to reverse-engineer as any poorly documented function in any language. CDK didn't invent this failure mode. It inherited it from general-purpose programming, and it also inherited that ecosystem's tools for catching it before it ships.
The assertions module (part of aws-cdk-lib, no third-party dependency required) gives you two testing approaches CloudFormation-only teams have no equivalent for. Fine-grained assertions test specific claims against the synthesized template, "this resource has this property with this value," and are AWS's recommended approach for test-driven development, since they fail with a message pointing at exactly what changed. Snapshot tests compare the whole synthesized template against a stored baseline, which lets you refactor a construct's internals freely and get an alert if the output shifts unexpectedly. Both integrate with Jest or Pytest, so infrastructure tests run in the same CI step as your application tests.
cdk-nag, a community tool maintained under the cdklabs GitHub org, runs as a synthesis-time validation plugin and checks constructs against AWS best-practice rule packs, producing a report you can gate a build on. Aspects, a lower-level mechanism, let you visit every construct in a scope during synthesis to apply cross-cutting checks, which is how cdk-nag itself works.
CloudFormation's counter-argument, "dumber but simpler, even with the repetition," is fair for a small, rarely-touched stack maintained by one team that already knows exactly what it does. It gets harder to defend the moment a second team, or a contractor, or a future hire, has to change that stack without the original author in the room. That's the reader this section is for: if you just recognized your own repository in the phrase "opaque construct," the fix isn't switching tools, it's applying the testing and boundary discipline CDK gives you access to and CloudFormation doesn't.
For the practices that keep a codebase legible before it needs an outside review, see our CDK best practices guide and how to structure CDK projects so they survive a handoff.
Discipline problems are solvable with practice and review, and CDK gives you more tools for both than plain CloudFormation does on its own.
The Ceiling Is CloudFormation's, Not CDK's: Quotas, Cost, and Other Myths
Because CDK deploys through CloudFormation, every quota below applies identically whether the template was hand-written or CDK-synthesized. CDK doesn't get special limits, and it doesn't pay differently.
| Quota | Value |
|---|---|
| Resources per template | 500 |
| Parameters per template | 200 |
| Outputs per template | 200 |
| Mappings per template | 200 |
| Template body size (direct API call) | 51,200 bytes (~51.2 KB) |
| Template body size (via S3 object) | 1 MB |
| Stack name length | 128 characters |
| Stacks per account | 2,000 |
| Resources per nested-stack operation | 2,500 |
AWS raised the resources-per-template ceiling from 200 to 500 on October 22, 2020, in the same update that raised parameters from 60 to 200, mappings from 100 to 200, outputs from 60 to 200, and the S3-hosted template size limit from 450 KB to 1 MB. That's a single, dated increase, sourced to AWS's own announcement.
When a template outgrows the official CloudFormation quotas, CDK's workarounds are the same ones a hand-written template uses: split resources across nested stacks, or stage the template through S3 instead of passing it inline. CDK adds two synthesis-time levers on top: the @aws-cdk/core:stackResourceLimit context key, which can loosen or disable CDK's own pre-flight resource-count check (it doesn't change what CloudFormation's API actually enforces), and suppressTemplateIndentation, which trims the whitespace CDK adds by default to keep generated templates under the byte-size limit.
The cost myth is worth killing directly. Per AWS's CloudFormation pricing page, native AWS::* and Alexa::* resources incur no CloudFormation service charge at all, whether the template came from cdk synth or a text editor. You pay for the underlying resources exactly as you would if you created them by hand. The only place CloudFormation charges anything is third-party resource types and custom Hooks: AWS bills $0.0009 per handler operation after roughly 1,000 free operations a month, plus $0.00008 per second for any operation running past its first free 30 seconds. That's orthogonal to this decision, since a hand-written template using a third-party registry extension pays the identical rate a CDK app using it pays.
Quotas are static; neither tool renegotiates them. What both tools shipped since early 2025 isn't static at all.
What's New in 2025-2026: CDK Refactor, Mixins, and CloudFormation's Own Refactoring
Neither tool sat still. If the comparison you're reading doesn't mention CDK Mixins or CloudFormation's drift-aware change sets, it predates them.
| Tool | Feature | Status | Date | What it does |
|---|---|---|---|---|
| CDK | CDK Toolkit Library (@aws-cdk/toolkit-lib) | GA | May 2025 | Programmatic access to CDK actions (synth, deploy, rollback, watch) without shelling out to the CLI |
| CDK | CDK Refactor (cdk refactor) | Preview, requires --unstable=refactor | Sept 2025 | Renames or moves constructs between stacks without CloudFormation treating them as replacements |
| CDK | CDK Mixins | GA | March 2026 | Composable traits applied to any L1 or L2 construct via .with() |
| CDK | cdk gc (garbage collection) | Opt-in, no confirmed GA date | Ongoing | Cleans up unreferenced S3/ECR assets left in the bootstrap bucket/repo |
| CloudFormation | Stack Refactoring (native API) | GA | Feb 2025 | Move resources between stacks or rename them while preserving properties and data |
| CloudFormation | IaC generator, targeted scans | GA feature addition | March 2025 | Scan specific resource types instead of the whole account when generating a template from existing resources |
| CloudFormation | Drift-aware change sets | GA | Nov 2025 | Three-way diff between new template, last-deployed template, and live state during deployment |
Two of these are worth a closer look because of how they relate. CDK Refactor renames a construct or moves it between stacks in code without CloudFormation deleting and recreating the resource, historically a real risk for anything stateful (a database, a queue, an S3 bucket). It generates a refactor plan comparing your code against deployed state, then calls CloudFormation's own Stack Refactoring API, the native capability that shipped in February 2025, to update logical IDs without touching physical resources. CDK Refactor is the interface; Stack Refactoring is the engine underneath. One constraint: adding, deleting, or modifying resources during a refactor requires splitting those into separate deployments.
Neither CDK Refactor nor cdk gc should be described as finished. CDK Refactor sits behind an explicit --unstable=refactor flag and AWS's own labeling states it "is subject to change"; cdk gc requires an unstable=gc opt-in, and AWS says its features "are subject to change," with no GA date confirmed at the time of writing. Treat both as useful in a sandbox, not yet as something to depend on in a production pipeline.
On the CloudFormation side, drift-aware change sets close a gap that used to force a choice between deploying blind or running drift detection as a separate, disconnected step: invoked via --deployment-mode REVERT_DRIFT on CreateChangeSet, CloudFormation now diffs the new template against both the last-deployed template and the live infrastructure state in the same operation, and can restore pre-deployment state automatically if a provisioning error occurs mid-deploy.
Neither tool "won" the last eighteen months. Picking a permanent winner between them was never actually required.
You Don't Have to Choose: Authoring and Rollout Are Separate Decisions
The framing so far has been binary because most objections are. One distinction prevents a common mistake here: how you author a template and how you roll it out are separate decisions. CDK versus CloudFormation is the authoring axis. StackSets versus CDK Pipelines is the rollout axis, and it cuts across the first rather than continuing it, because a template from cdk synth is an ordinary CloudFormation template that a StackSet distributes as readily as one you typed by hand.
StackSets is CloudFormation's native mechanism for pushing the same stack to many accounts and Regions in a single operation. With service-managed permissions integrated into AWS Organizations, a StackSet targeting an OU deploys automatically as accounts join or leave it, which is exactly the shape of a governance baseline: compliance controls, shared logging, a security guardrail that every account should have without an app team remembering to add it. One real constraint worth flagging before you standardize on it: StackSets with service-managed permissions can't deploy templates containing macros or transforms, which matters if your governance templates lean on AWS::LanguageExtensions constructs like Fn::ForEach.
CDK Pipelines answers the same multi-target problem in a different shape. You define Stage objects, each potentially targeting a different account or Region, add them to a pipeline, and CDK Pipelines works out dependency order and publishes assets automatically. Grouping stages into a Wave deploys several in parallel, the closest CDK-side analog to a StackSet's single-operation fan-out, though implemented as CodePipeline actions rather than a native CloudFormation primitive.
One operational catch is worth knowing before production: every target account and Region a CDK Pipeline deploys into has to be bootstrapped independently, something StackSets never requires since it deploys ordinary CloudFormation stacks without a CDK-specific toolkit stack. If you ever see the CDK Pipelines error "Policy contains a statement with one or more invalid principals," it means exactly this, the target environment was never bootstrapped.
The decision criterion in practice: StackSets when you need the same stack in many accounts in one operation, a compliance baseline or shared logging. CDK Pipelines when app teams need different stacks with sequencing, testing, and approvals between environments. That choice is about the shape of the rollout, not about which tool wrote the template.
Two things do couple the axes in practice. A synthesized template referencing assets, bundled Lambda code or a container image, points at the bootstrap bucket those assets were published to, so it doesn't travel to other accounts as a self-contained file. And the transform restriction above rules out some synthesized output. A synthesized template that is both asset-free and transform-free clears both bars, which is why the familiar split holds up: StackSets for account-wide guardrails, CDK Pipelines for the application stacks on top.
Excalidraw diagram loading.
One more mix-up is worth clearing up before the verdict, not CDK versus CloudFormation, but CDK versus a tool with a similar name that does something completely different.
CDK vs AWS SDK vs SAM: Untangling the Acronyms
These three get confused constantly, and they're not actually competing with each other.
CDK runs at deploy time. It defines and provisions infrastructure, then its job is done until the next deployment. The AWS SDK runs at runtime, inside your already-deployed application, calling AWS APIs against resources that already exist. A typical app uses CDK to provision a Lambda function and a DynamoDB table, then uses the SDK inside that Lambda's code to read and write items in that table. They're complementary: the deploy-time-versus-runtime distinction answers almost any "is this a CDK thing or an SDK thing" question you'll run into.
SAM is a CloudFormation macro, technically a Transform, specialized for serverless resources. It's a sibling authoring option to CDK rather than a third axis in this decision: SAM templates are still CloudFormation, expanded through a transform before deployment. Some Lambda-heavy teams stay on SAM for its serverless shorthand and local testing tooling, a reasonable choice for a genuinely serverless-only team that wants less to learn.
If your actual comparison is CDK against a multi-cloud tool rather than against plain CloudFormation, that's a different decision with different trade-offs (state management, provider ecosystems, deployment speed), and our dedicated AWS CDK vs Terraform guide covers it in full rather than diluting this comparison across a third tool. One more name worth a single mention: AWS Blocks, an application-layer framework for composing backends without touching infrastructure tooling directly, sits one abstraction level above this entire decision and isn't an alternative to either CDK or CloudFormation.
With the acronyms sorted, here's the actual verdict.
So, CDK or CloudFormation? The Heuristic That Actually Holds Up
Strip away the objections and their fixes, and the decision comes down to a heuristic that multiple engineers converge on independently once they've run both tools long enough: large or complex projects, teams that want code review and testing on infrastructure changes, and multi-environment deployments favor CDK. Small, simple, rarely-touched, or governance-baseline stacks favor plain CloudFormation. It isn't a hedge. It's the same conclusion reached from different angles: bootstrap overhead only pays for itself against enough deployment volume to amortize it, and construct-level testing only matters once a codebase is large enough that a human can't hold the whole thing in their head.
| Factor | Favors CDK | Favors CloudFormation |
|---|---|---|
| Project size | Growing, many resources, multiple stacks | Small, fixed scope, rarely expands |
| Team composition | Developers comfortable with TypeScript, Python, or another supported language | Ops-focused team, prefers declarative templates |
| Change frequency | Frequent iteration, needs fast feedback and tests | Deployed once, touched rarely |
| Role in the architecture | Application infrastructure, owned by a product team | Guardrail baseline a StackSet fans out; self-contained templates travel better |
If your project matches most of the left column, CDK's bootstrap tax and abstraction learning curve pay for themselves quickly. If it matches the right column, plain CloudFormation's lower ceremony is the honest choice, not a compromise.
Frequently Asked Questions
Does CDK cost more than CloudFormation?
Should I learn CloudFormation before AWS CDK?
Is cdk refactor safe to use in production yet?
What's the maximum number of resources in a single CloudFormation stack?
Can a CDK app deploy without going through CloudFormation?
Is cdk migrate production-ready?
Is AWS Blocks a CDK or CloudFormation alternative?
Can I mix hand-written CloudFormation stacks and CDK-managed stacks in the same AWS account?
Key Takeaways
CloudFormation isn't deprecated, and CDK's existence makes it more load-bearing, not less. Every objection engineers raise against CDK is real, and every one has a concrete answer: bootstrap once, re-run it when the template version moves, and treat it as a Tier-0 asset, drop to L1 or addPropertyOverride when a construct lags, use the env property and context values instead of CloudFormation parameters, and lean on the assertions module and cdk-nag before the codebase gets hard to review. The heuristic that holds up: large, actively-developed, multi-environment projects favor CDK; small, stable, governance-baseline stacks favor plain CloudFormation. Both tools kept shipping through 2025 and 2026, so revisit this whenever either changes shape again.
If you've landed on CDK for your next project, the natural next step is getting the first app deployed correctly rather than working it out by trial and error. Our guide to deploying your first CDK app walks through that setup end to end.
Next step
Is the CDK Code You Inherited Actually Sound?
The bootstrap roles, the escape hatches, and the 'great until you maintain someone else's CDK' problem this article walked through are exactly what we review first: construct boundaries, deployment flow, and reuse patterns, delivered as a written report plus a pull request that shows the fix in code.