<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cloudformation on Backend Engineering Strategy Tools</title><link>https://backend-engineering-strategy-tools.github.io/site/tags/cloudformation/</link><description>Recent content in Cloudformation on Backend Engineering Strategy Tools</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Mon, 01 Jan 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://backend-engineering-strategy-tools.github.io/site/tags/cloudformation/index.xml" rel="self" type="application/rss+xml"/><item><title>AWS CDK</title><link>https://backend-engineering-strategy-tools.github.io/site/public-notes/infra-as-code/cdk/</link><pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/public-notes/infra-as-code/cdk/</guid><description>&lt;p&gt;AWS CDK (Cloud Development Kit) lets you define infrastructure using real programming languages — Java, TypeScript, Python — rather than a DSL. You write code, CDK synthesizes it into a CloudFormation template, and CloudFormation deploys it to AWS.&lt;/p&gt;
&lt;p&gt;The appeal is obvious if your team lives in Java: familiar language, familiar tooling, loops and abstractions, unit tests with JUnit. No HCL to learn.&lt;/p&gt;
&lt;p&gt;In practice it is slower and more cumbersome than it looks, and the CloudFormation layer underneath causes real problems.&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How it works
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Write Java (imperative)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mvn package&lt;/code&gt; — compile and run unit tests&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cdk synth&lt;/code&gt; — generate the CloudFormation template&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cdk diff&lt;/code&gt; — compare deployed stack with current state (optional)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cdk deploy&lt;/code&gt; — deploy stack to AWS via CloudFormation&lt;/li&gt;
&lt;li&gt;CloudFormation makes the API calls to AWS&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The key thing to understand: CDK does not talk to AWS directly. It generates CloudFormation, and CloudFormation does the work. Everything downstream of &lt;code&gt;cdk synth&lt;/code&gt; is CloudFormation behaviour, not CDK behaviour.&lt;/p&gt;
&lt;h2 id="the-cloudformation-problem"&gt;The CloudFormation problem
&lt;/h2&gt;&lt;p&gt;CloudFormation does not track changes made outside of stacks. Someone logs into the console and modifies a security group — CloudFormation does not know, your CDK code does not know, and &lt;code&gt;cdk diff&lt;/code&gt; will not show it. That is drift, and it accumulates silently until a deployment overrides something that was manually changed in production, or a &lt;code&gt;cdk destroy&lt;/code&gt; removes something that was depended on.&lt;/p&gt;
&lt;p&gt;CloudFormation does have a drift detection feature, but it is not part of the normal workflow — you trigger it manually from the console, it shows you the diff, and then expects you to go fix it yourself.&lt;/p&gt;
&lt;p&gt;Compared to &lt;a class="link" href="../terraform/" &gt;Terraform&lt;/a&gt;, which maintains its own state file and surfaces drift explicitly in &lt;code&gt;terraform plan&lt;/code&gt;, this is a meaningful operational weakness.&lt;/p&gt;
&lt;h2 id="cross-stack-dependencies"&gt;Cross-stack dependencies
&lt;/h2&gt;&lt;p&gt;Splitting infrastructure into smaller stacks is the right instinct — smaller blast radius, faster deploys, clearer ownership. The problem is how CloudFormation handles values shared between stacks.&lt;/p&gt;
&lt;p&gt;When Stack A exports a value (a VPC ID, a security group ARN) and Stack B imports it, CloudFormation creates a hard dependency. You cannot modify or delete that export while any other stack is consuming it. CloudFormation will block the update and leave you stuck — Stack A cannot deploy because the export is in use, and Stack B may be in a broken state because it depends on something that no longer exists as expected. Getting out requires carefully coordinating the removal of the import before you can change the export.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fix: use SSM Parameter Store instead of CloudFormation exports.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Stack A writes its outputs to SSM:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;StringParameter.&lt;span style="color:#a6e22e"&gt;Builder&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;VpcIdParam&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;parameterName&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;/infra/vpc/id&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;stringValue&lt;/span&gt;(vpc.&lt;span style="color:#a6e22e"&gt;getVpcId&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;build&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Stack B reads from SSM at deploy time:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;String vpcId &lt;span style="color:#f92672"&gt;=&lt;/span&gt; StringParameter.&lt;span style="color:#a6e22e"&gt;valueForStringParameter&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;/infra/vpc/id&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No CloudFormation export, no hard dependency, no blocked deployments. Stacks can be updated and deployed independently. SSM also gives you a clean place to browse shared infrastructure values and reference them from outside CDK (application config, scripts, other tools).&lt;/p&gt;
&lt;h2 id="testing"&gt;Testing
&lt;/h2&gt;&lt;p&gt;Testing in CDK is limited to validating the synthesized CloudFormation template — you are not testing infrastructure behaviour, you are testing that your code generates the JSON you expect:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unit tests&lt;/strong&gt; — JUnit assertions against the synthesized template (e.g. &amp;ldquo;does this stack contain an S3 bucket with versioning enabled&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration tests&lt;/strong&gt; — deploy to an isolated environment and validate via AWS SDK&lt;/li&gt;
&lt;li&gt;No native plan/apply preview; you must deploy to see what actually happens&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pros"&gt;Pros
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Familiar Java constructs — loops, conditionals, reusable classes&lt;/li&gt;
&lt;li&gt;Full IDE support, refactoring, type safety&lt;/li&gt;
&lt;li&gt;Unit testing with JUnit&lt;/li&gt;
&lt;li&gt;Good for teams already invested in Java who want infrastructure close to application code&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cons"&gt;Cons
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Generates CloudFormation — debugging complex stacks means reading generated JSON/YAML&lt;/li&gt;
&lt;li&gt;More boilerplate than HCL for straightforward infrastructure&lt;/li&gt;
&lt;li&gt;Drift detection relies on CloudFormation, which has no visibility into out-of-band changes&lt;/li&gt;
&lt;li&gt;Importing existing infrastructure can be awkward&lt;/li&gt;
&lt;li&gt;Smaller community example base compared to Terraform, especially in Java vs TypeScript/Python&lt;/li&gt;
&lt;li&gt;Deployments are slower than Terraform&amp;rsquo;s direct API approach&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="vs-terraform"&gt;vs Terraform
&lt;/h2&gt;&lt;p&gt;For repeatable, standardised infrastructure with a clear plan/apply workflow and reliable drift detection, &lt;a class="link" href="../terraform/" &gt;Terraform&lt;/a&gt; is the stronger choice. CDK makes sense when infrastructure is deeply coupled to application code and the team is committed to a single language across both.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.aws.amazon.com/cdk/v2/guide/home.html" target="_blank" rel="noopener"
 &gt;AWS CDK documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.aws.amazon.com/cdk/api/v2/" target="_blank" rel="noopener"
 &gt;AWS CDK API reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cdkpatterns.com/" target="_blank" rel="noopener"
 &gt;CDK Patterns&lt;/a&gt; — community example library&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/aws/aws-cdk" target="_blank" rel="noopener"
 &gt;AWS CDK GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>