SYSTEM NOTICE

Auto translation by AI. Be sure, accuracy, nuances and authorial intent may not be fully reflected.
見出し画像

Why I switched from CloudFormation to AWS CDK after years of writing it

Introduction

If you are managing AWS infrastructure as code, the first thing that comes to mind is likely CloudFormation (hereinafter Cfn).

You write it in YAML or JSON, create a stack, and deploy it.

There was a time when I thought that was enough.

However, my perspective changed after I started using CDK.

I never expected the feeling of "programming infrastructure" to be this different.

In this article, I will summarize specifically what changes when you use CDK, focusing on a comparison with Cfn.

What is painful about CloudFormation

First, I will be honest.

You can use Cfn once you get used to it.

But it becomes painful as the scale grows.

Pain 1: YAML becomes massive

The more resources you have, the longer the files become.

500-line or 1000-line YAML files are not rare.

Similar descriptions are repeated, and it becomes unclear where you should make changes.

Pain 2: Cannot absorb repetition

When you want to create almost the same configuration for dev and prod environments, Cfn handles it with Parameters or Conditions, but the syntax is cumbersome and prone to errors.

As a result, you often end up with multiple copies of YAML files.

Pain 3: No type checking

You cannot detect errors while writing YAML.

You only realize the property name was wrong after you deploy.

This back-and-forth quietly eats up your time.

Pain point 4: Cannot write logic

“I only want to create this resource when the flag is true,” or “I want to dynamically add the environment name to the resource name”—while it's not impossible to struggle through with Cfn Conditions or !Sub, there are limits to complex conditional branching.

What is AWS CDK?

AWS CDK (Cloud Development Kit) is a framework that allows you to define AWS infrastructure using programming languages like TypeScript, Python, and Java.

Since it ultimately generates and deploys a Cfn template,the backend is the same as Cfn.

However, what you write is program code.

// CDKでVPCを作る例(TypeScript)
const vpc = new ec2.Vpc(this, 'MyVpc', {
  maxAzs: 2,
  natGateways: 1,
});

Writing the equivalent in Cfn would result in dozens of lines of YAML just for this.

Comparison between Cfn and CDK

Language used

  • CloudFormation: YAML / JSON

  • AWS CDK: TypeScript / Python, etc.

Amount of code

  • CloudFormation: High

  • AWS CDK: Low (it is abstracted)

Repetitive tasks

  • CloudFormation: Difficult (tends to involve copy-pasting)

  • AWS CDK: Easily handled with loops and functions

Type checking

  • CloudFormation: None (discovered at deployment)

  • AWS CDK: Yes (real-time in editor)

Conditional branching

  • CloudFormation: Conditions syntax (complex)

  • AWS CDK: Can be written naturally with if statements

Reusability

  • CloudFormation: Stack-based

  • AWS CDK: Can be modularized as Constructs

Learning cost

  • CloudFormation: Learn AWS syntax

  • AWS CDK: Programming knowledge required

Existing assets

  • CloudFormation: Abundant

  • AWS CDK: Rapidly expanding

Deployment target

  • CloudFormation: CFn stack

  • AWS CDK: CFn stack (same)

What changes when using CDK: A look at concrete examples

1. Repetitive tasks can be written with loops

When you want to create multiple S3 buckets for each environment.

In the case of Cfn:

DevBucket:
  Type: AWS::S3::Bucket
  Properties:
    BucketName: myapp-dev-bucket

StageBucket:
  Type: AWS::S3::Bucket
  Properties:
    BucketName: myapp-stage-bucket

ProdBucket:
  Type: AWS::S3::Bucket
  Properties:
    BucketName: myapp-prod-bucket

In the case of CDK:

const envs = ['dev', 'stage', 'prod'];
for (const env of envs) {
  new s3.Bucket(this, `${env}Bucket`, {
    bucketName: `myapp-${env}-bucket`,
  });
}

While doing the same thing, additions, changes, and deletions can be handled in a single line.

(2) Can be modularized with Constructs

The greatest strength of CDK is the concept of "Constructs".

You can define combinations of frequently used resources as reusable components.

For example, if you bundle a set of "ECS cluster + ALB + security group" into a single Construct, you can call it in one line in other projects or stacks.

// 自作ConstructをStackで使う例
const api = new MyEcsApiConstruct(this, 'Api', {
  vpc,
  environment: 'prod',
  containerPort: 8080,
});

You can do something similar with NestedStacks in Cfn, but because there is no benefit of types, it becomes difficult to grasp the parameters that can be passed.

(3) Real-time completion and type checking in the editor

When you write CDK in TypeScript, editors like VSCode support the following in real-time.

  • Property name completion (check what can be set on the spot)

  • Immediate detection of type errors (notice mistakes before deployment)

  • Convert to Cfn template with cdk synth to verify

Mistakes that were often noticed only after deployment in Cfn can now be prevented while writing.

(4) Conditional branching can be written naturally

Conditions such as enabling Deletion Protection only in the production environment can be written with standard if statements.

const isProd = props.environment === 'prod';

new rds.DatabaseInstance(this, 'DB', {
  // ...
  deletionProtection: isProd,
  removalPolicy: isProd
    ? cdk.RemovalPolicy.RETAIN
    : cdk.RemovalPolicy.DESTROY,
});

It is far more readable and easier to manage than using Cfn Conditions.

(5) Can choose the level of abstraction: L1 / L2 / L3

CDK has three levels for resource definition.

L1

  • Common name: Cfn resources

  • Content: 1:1 correspondence with CloudFormation. Classes with the Cfn prefix

L2

  • Common name: High-level Constructs

  • Content: Automatically includes default settings such as security groups

L3

  • Common name: Patterns

  • Content: Standard configurations that bundle sets of multiple resources

Basically, if you use L2, "best practices" such as default IAM policy settings are applied automatically.

You only need to drop down to L1 when you want fine-grained control.

Since Cfn is always equivalent to L1, you have to be aware of everything yourself, such as missing IAM policy settings.

When to use CDK and when you don't need to

When CDK is suitable

  • You want to reuse similar configurations across multiple environments (dev/stage/prod)

  • There are many resources, and you want to create reusable components

  • You are managing infrastructure as a team and need code that is easy to review

  • You are comfortable with TypeScript, Python, etc.

When sticking with Cfn is fine

  • Existing Cfn templates are running stably and do not need to be changed

  • The number of resources is small, and it can be completed with a simple configuration

  • There is a team rule to manage everything using only YAML

You don't have to migrate to CDK all at once.

You can start writing new resources in CDK while keeping existing ones in Cfn.

Points to keep in mind when starting with CDK

I recommend choosing TypeScript

Although CDK supports Python, Java, C#, etc., TypeScript is the easiest to work with due to the abundance of documentation and samples.

Even if you are not used to JavaScript, the type system provides autocompletion, making it surprisingly easy to write.

Get into the habit of reading the YAML generated by cdk synth

When you are not used to it, it is easy to end up in a state where you don't know what is being created by the Cfn templates that CDK automatically generates.

By regularly checking the output of cdk synth, you can verify that no unintended resources are being created.

You can automate security checks with cdk-nag

By using a library called cdk-nag, you can detect issues like lack of least privilege in IAM or missing encryption settings at the code level.

It is effective for reducing the cost of security reviews.

Summary

CloudFormation is still a powerful and active tool.

However, as the scale grows, the limitations of "repetition," "conditional branching," and "modularization" become apparent.

CDK is an approach that overcomes these limitations through the power of programming.

Since the underlying mechanism is the same as Cfn, you can migrate while leveraging your existing knowledge.

If you can write Cfn but haven't tried CDK yet, I encourage you to start by writing one new resource in CDK.

Once you get used to it, you won't be able to go back to Cfn.

If you found this article helpful, please give it a like or follow me; it would be a great encouragement.

いいなと思ったら応援しよう!