algonote(en)

There's More Than One Way To Do It

Yukkuri AWS CDK (Python)

This is a hands-on guide for AWS CDK created with ChatGPT. It may contain errors.

Chapter 1: Introduction

In this book, we will learn AWS CDK v2 using Python, through practical, code-driven exercises. Yukkuri characters will appear as friendly guides throughout the text.


1.1 What is Infrastructure as Code (IaC)?

📘 Technical Explanation

Infrastructure as Code (IaC) is the practice of managing cloud infrastructure using source code instead of clicking through the AWS console.

Key Characteristics

  • Automatable
  • Repeatable
  • Version-controlled
  • Testable and reviewable
  • Enables CI/CD and DevOps practices

Example: instead of clicking to create an EC2 instance, we express it in code.

from aws_cdk import (
    Stack,
    aws_ec2 as ec2,
)
from constructs import Construct

class SimpleServerStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        ec2.Instance(
            self, "ExampleInstance",
            instance_type=ec2.InstanceType("t3.micro"),
            machine_image=ec2.MachineImage.latest_amazon_linux(),
            vpc=ec2.Vpc.from_lookup(self, "DefaultVPC", is_default=True)
        )

🗣️ Yukkuri Commentary

Reimu: So IaC means we stop clicking buttons?
Marisa: Yes! Clicking is pain. Code is love. Code is life.
Reimu: Predictable deployments sound nice.
Marisa: And when everything breaks, we can rebuild it instantly! very professional


1.2 Why use CDK v2 and why Python?

📘 Technical Explanation

Why CDK v2?

  • Official AWS development framework
  • One unified library: aws-cdk-lib
  • Faster updates for new AWS services
  • Construct-based architecture = high-level abstractions
  • Reusable components across projects

Why Python?

  • Clean syntax & fast to learn
  • Widely used in automation and serverless
  • Works well with AWS Lambda
  • Rich tooling ecosystem: pip, venv, pytest
cdk init app --language python

Creates a structure like:

.
├─ app.py
└─ <project_name>/
   └─ <project_name>_stack.py

🗣️ Yukkuri Commentary

Reimu: Why not Terraform?
Marisa: Terraform is great, but CDK is extra spicy AWS-native magic power!
Reimu: And Python is easier to read than YAML.
Marisa: YAML indentation boss fight is over. Python wins.


1.3 How this book is structured & how to use it

📘 Structure

Section Focus
Foundations IaC basics, CDK concepts
Hands-on Labs Build real AWS architectures
Advanced Topics CI/CD, multi-stack, security
Operations Monitoring, debugging, cost controls
Appendix Cheatsheets & reusable patterns

Suggested Workflow

Read → Write code → Deploy → Break → Debug → Deploy again

Mental model: Treat infrastructure like software. It has versions, tests, refactors, and pull requests.


🗣️ Yukkuri Commentary

Reimu: So I need to actually type the code?
Marisa: Yes. Copy-pasting is fine… but debugging is the true dojo!
Reimu: Break things to learn, huh. Sounds like real DevOps.
Marisa: If you never broke production, you haven't lived.


1.4 Prerequisites

✅ Before you start, you should have:

Requirement Notes
AWS account Free tier works
Python 3.8+ Virtual env recommended
Node.js Required for CDK CLI
AWS CLI Auth & config
Git Version control

Install CDK & Setup Project

npm install -g aws-cdk

mkdir cdk-intro && cd cdk-intro

cdk init app --language python

Activate virtual environment:

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Configure AWS credentials:

aws configure

🗣️ Yukkuri Commentary

Reimu: Why do I need Node.js if I'm writing Python?
Marisa: CDK CLI runs on Node. The CDK gods demand tribute.
Reimu: And AWS CLI config… always terrifying.
Marisa: Type the credentials correctly, and pray. Always pray.


✅ Chapter Summary

You learned:

  • What IaC is and why it matters
  • Why CDK v2 is powerful
  • Why this book uses Python
  • How to prepare your environment

Next: We will deploy our first CDK stack.

Reimu: Finally some action!
Marisa: Yes. Time to spawn real AWS resources.
Reimu: And hopefully not get billed into oblivion.
Marisa: Free tier is our shield. Mostly.

Chapter 2: Getting Started with CDK v2 in Python

2.1 Overview of CDK v2: Changes from v1, Benefits

AWS CDK v2 introduces a simplified, unified experience:

Feature CDK v1 CDK v2
Library Many npm modules Single module: aws-cdk-lib
Constructs @aws-cdk/core constructs package
Stability Mix of versioned and unstable APIs Stable API Guarantees
Maintenance Legacy Actively maintained

Key benefits:

  • Simpler installation & imports
  • Faster updates for new AWS features
  • Community adoption + examples everywhere
  • Predictable API stability
# CDK v2 import example
from aws_cdk import (
    Stack,
    aws_s3 as s3,
)

🗣 Yukkuri Commentary

Reimu: So v2 is like “CDK but not suffering”?
Marisa: Exactly. Less dependency chaos, more cloud magic.
Reimu: Developers love less pain.
Marisa: Yes. Pain is for runtime bugs, not setup.


2.2 Setting Up the Development Environment

Install Node.js

Required for the CDK CLI (even with Python CDK apps)

brew install node   # macOS
sudo apt-get install nodejs npm  # Ubuntu/Debian

Install CDK CLI

npm install -g aws-cdk

Verify installation

cdk --version

Install Python 3.8+

python3 --version

Virtual Environment

python3 -m venv .venv
source .venv/bin/activate   # macOS / Linux
.venv\Scripts\activate      # Windows

🗣 Yukkuri Commentary

Reimu: Why do we need Node.js again if we use Python?
Marisa: Because CDK CLI runs on Node. Respect the multi-language gods.
Reimu: Multilingual pain…
Marisa: The cloud demands blood— and toolchains.


2.3 Create Your First CDK Python Project

mkdir my-first-cdk && cd my-first-cdk
cdk init app --language python

Install dependencies:

source .venv/bin/activate
pip install -r requirements.txt

🗣 Yukkuri Commentary

Reimu: That generated a lot of files.
Marisa: Yes. Scaffolding magic. Like a cookie cutter but for cloud things.
Reimu: I see folder, I trust.


2.4 CDK Project Structure & Lifecycle

Generated structure:

my-first-cdk/
├── app.py
├── requirements.txt
└── my_first_cdk
    └── my_first_cdk_stack.py

CDK Lifecycle

Step Command Purpose
Synthesize cdk synth Generate CloudFormation
Diff cdk diff Show what will change
Deploy cdk deploy Build & deploy stack
Destroy cdk destroy Clean resources

First Stack Example

from aws_cdk import (
    Stack,
    aws_s3 as s3,
)
from constructs import Construct

class MyFirstCdkStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        s3.Bucket(self, "MyBucket",
            versioned=True
        )

🗣 Yukkuri Commentary

Marisa: Synth! Diff! Deploy! Destroy!
Reimu: Are those AWS spells?
Marisa: Yes. Deploy is Fireball. Destroy is Meteor.


2.5 Understanding aws_cdk / aws-cdk-lib & Constructs

CDK Key Concepts

Concept Description
Construct Cloud component (S3 bucket, Lambda, VPC)
Stack Deployment unit
App Collection of stacks
Construct Library Ready-to-use AWS components

Import Patterns

from aws_cdk import (
    Stack,
    aws_lambda as _lambda,
    aws_dynamodb as dynamodb,
)
from constructs import Construct

Creating a Lambda and DynamoDB Table

_lambda.Function(
    self, "MyFunction",
    runtime=_lambda.Runtime.PYTHON_3_9,
    handler="handler.main",
    code=_lambda.Code.from_asset("lambda")
)

dynamodb.Table(
    self, "Table",
    partition_key={"name": "id", "type": dynamodb.AttributeType.STRING}
)

🗣 Yukkuri Commentary

Reimu: Construct library is like LEGO blocks?
Marisa: Exactly. Except the bricks create real bills if you forget to delete them.
Reimu: Gently puts wallet behind back


2.6 Bootstrapping & Cost Basics

What is Bootstrapping?

CDK needs AWS resources for deployments (S3 bucket, roles).

Run once per region/account:

cdk bootstrap

Basic AWS Billing Safety

  • Use Free Tier resources when possible
  • Avoid unnecessarily large instances (e.g., m5.4xlarge)
  • Delete stacks when finished:
cdk destroy

🗣 Yukkuri Commentary

Reimu: Bootstrapping feels like setting the stage.
Marisa: Yes. Before the cloud musical begins!
Reimu: And destroy stacks to avoid sadness from AWS bills.
Marisa: Financial death is real. Respect the billing gods.


✅ Chapter 2 Summary

You now know how to:

  • Understand CDK v2 advantages
  • Install CDK CLI, Python env
  • Initialize a CDK project
  • Understand the CDK lifecycle
  • Use Construct Library
  • Bootstrap and avoid cost disasters

Chapter 3: Core Concepts and Abstractions

In this chapter we explore fundamental CDK abstractions. Master these concepts, and you unlock the full power of CDK.


3.1 Constructs: L1, L2, L3 — What They Are & When to Use

CDK defines AWS resources in layers:

Level Name Description Example
L1 CloudFormation bindings Direct 1:1 mapping CfnBucket
L2 Opinionated high-level constructs Best-practice defaults Bucket
L3 Patterns Complete architectures aws_s3_deployment.BucketDeployment

Example: L1 vs L2

L1 Construct

from aws_cdk import aws_s3 as s3

s3.CfnBucket(self, "RawBucket",
    bucket_name="my-low-level-bucket"
)

L2 Construct

s3.Bucket(self, "NiceBucket",
    versioned=True,
    encryption=s3.BucketEncryption.S3_MANAGED
)

L2 saves time, L1 gives ultimate control.


🗣 Yukkuri Commentary

Reimu: So L2 is “safe defaults,” and L1 is “danger mode”?
Marisa: Exactly! L1 is like driving without seatbelts—fast, scary, and sometimes necessary.
Reimu: L3 sounds like pre-made lunch boxes.
Marisa: Bento DevOps.


3.2 Stacks, Apps, and Assemblies

Definitions

Term Meaning
App Entry point to CDK execution
Stack Deployment unit (CloudFormation stack)
Assembly Synthesis output (CloudFormation templates + metadata)

Example Project Entry: app.py

#!/usr/bin/env python3
from aws_cdk import App
from my_app.my_stack import MyStack

app = App()
MyStack(app, "MyStack")
app.synth()

Stack Example

from aws_cdk import Stack, aws_sqs as sqs
from constructs import Construct

class MyStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        sqs.Queue(self, "MyQueue")

🗣 Yukkuri Commentary

Reimu: So the app summons stacks?
Marisa: Yes. The app is the summoner. The stacks are the creatures.
Reimu: Cloud Pokémon.
Marisa: But AWS charges per summon.


3.3 Context, Environment, and Cross-Account / Cross-Region

Context

Load parameters at runtime:

cdk deploy --context stage=prod

Inside Python:

stage = self.node.try_get_context("stage")
print(f"Deploying to {stage}")

Environment

Specify account & region:

from aws_cdk import Environment

MyStack(app, "ProdStack",
    env=Environment(account="123456789012", region="us-east-1")
)

Cross-Account Notes

  • Bootstrapping required per account
  • Deploy roles needed
  • Avoid passing secrets across stacks

🗣 Yukkuri Commentary

Reimu: Multi-account deployments sound scary.
Marisa: They are. Like AWS billing demons spawning across universes.
Reimu: I shall respect the context spell.


3.4 Assets, Bundling, Deployment Artifacts

CDK packages local files as assets (Lambda code, Web assets, Docker build contexts).

Lambda with assets

from aws_cdk import aws_lambda as _lambda

_lambda.Function(
    self, "Handler",
    runtime=_lambda.Runtime.PYTHON_3_9,
    handler="index.handler",
    code=_lambda.Code.from_asset("lambda")
)

Bundling Example (Container build)

from aws_cdk import BundlingOptions

_lambda.Function(
    self, "BundledLambda",
    runtime=_lambda.Runtime.PYTHON_3_9,
    handler="app.handler",
    code=_lambda.Code.from_asset("./src",
        bundling=BundlingOptions(
            image=_lambda.Runtime.PYTHON_3_9.bundling_image,
            command=["bash", "-c", "pip install -r requirements.txt -t /asset-output && cp -r . /asset-output"]
        )
    )
)

🗣 Yukkuri Commentary

Reimu: So bundling is like packing lunch for Lambda?
Marisa: Yes, we send it to the cloud school.
Reimu: Do we include dependencies?
Marisa: Always. Cloud children get hungry.


3.5 Versioning & Dependencies of aws-cdk-lib in Python

Install specific version:

pip install "aws-cdk-lib==2.1.0"
pip install "constructs>=10.0.0,<11.0.0"

Check versions:

pip list | grep cdk

Upgrade strategy

  • Pin versions in requirements.txt
  • Upgrade regularly
  • Test in sandbox environment

🗣 Yukkuri Commentary

Reimu: Dependency version hell?
Marisa: Not as bad as npm hell.
Reimu: True. Python hell is warm, not flaming.


3.6 Naming Conventions, snake_case & Type Hints

CDK uses snake_case for Python APIs:

bucket = s3.Bucket(self, "MyBucket",
    removal_policy=s3.RemovalPolicy.DESTROY
)

Type Hint Example

from typing import Optional

def build_bucket(self, name: str, versioned: Optional[bool] = True):
    ...

Common Gotcha

Construct IDs use PascalCase, resource props use snake_case.

bucket = s3.Bucket(self, "AppDataBucket")  # ID

🗣 Yukkuri Commentary

Reimu: snake_case + PascalCase… mixed conventions!
Marisa: Yes. Fear not. Embrace the duality.
Reimu: Dual-case discipline: required for cloud enlightenment.


✅ Chapter Summary

In this chapter you learned:

  • L1/L2/L3 constructs & when to use them
  • Stacks, Apps, and Assembly outputs
  • Context & environments
  • Assets & bundling
  • Version pinning & dependency discipline
  • Naming rules + type hint discipline

Chapter 4: Hands-On Project I — Simple Web Application Infrastructure

In this chapter we build a simple web application using:

  • S3 (static hosting)
  • CloudFront (CDN)
  • Lambda (serverless API)
  • API Gateway (HTTP entry point)
  • DynamoDB (storage)

4.1 Requirements: static website or simple REST API

We will create:

  • A static website (HTML/JS) hosted in S3
  • A CloudFront distribution for global caching
  • A serverless API endpoint (/hello)
  • Python Lambda that writes to DynamoDB
  • CloudFormation + CDK automation

Project architecture:

Client Browser -> CloudFront -> S3 (static site)
                      \
                       -> API Gateway -> Lambda -> DynamoDB

🗣️ Yukkuri Commentary

Reimu: Building a whole app already?
Marisa: Yes! Real cloud isn’t for looking — it's for deploying!
Reimu: As long as it doesn't summon bills.
Marisa: Free tier is our shield. Mostly.


4.2 S3 Bucket for Website + CloudFront Distribution

Install CDK S3 Deployment

pip install aws-cdk-lib constructs
pip install aws-cdk.aws-s3-deployment

Define Bucket + CloudFront

infrastructure/web_stack.py

from aws_cdk import (
    Stack,
    aws_s3 as s3,
    aws_cloudfront as cloudfront,
    aws_s3_deployment as s3deploy,
)
from constructs import Construct

class WebStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        self.bucket = s3.Bucket(self, "WebBucket",
            website_index_document="index.html",
            public_read_access=False
        )

        self.distribution = cloudfront.CloudFrontWebDistribution(
            self, "WebDistribution",
            origin_configs=[
                cloudfront.SourceConfiguration(
                    s3_origin_source=cloudfront.S3OriginConfig(
                        s3_bucket_source=self.bucket
                    ),
                    behaviors=[cloudfront.Behavior(is_default_behavior=True)]
                )
            ]
        )

        s3deploy.BucketDeployment(
            self, "DeployStaticSite",
            destination_bucket=self.bucket,
            sources=[s3deploy.Source.asset("./web")]
        )

Place your HTML file in web/index.html.


🗣️ Yukkuri Commentary

Reimu: So CloudFront makes my website fast worldwide?
Marisa: Yes. It is CDN magic.
Reimu: Like teleportation but for packets.
Marisa: Exactly. AWS sorcery.


4.3 Lambda (Python) + API Gateway Endpoint

Lambda Code

lambda/handler.py

import json
import boto3
import os

dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table(os.environ["TABLE_NAME"])

def handler(event, context):
    name = event.get("queryStringParameters", {}).get("name", "visitor")

    table.put_item(Item={"id": name})

    return {
        "statusCode": 200,
        "body": json.dumps({"message": f"Hello, {name}!"})
    }

CDK Stack for API

from aws_cdk import (
    aws_lambda as _lambda,
    aws_apigateway as apigw,
)

class ApiStack(Stack):
    def __init__(self, scope: Construct, id: str, table, **kwargs):
        super().__init__(scope, id, **kwargs)

        self.func = _lambda.Function(
            self, "HelloFunction",
            runtime=_lambda.Runtime.PYTHON_3_9,
            handler="handler.handler",
            code=_lambda.Code.from_asset("lambda"),
            environment={"TABLE_NAME": table.table_name}
        )

        self.api = apigw.LambdaRestApi(
            self, "ApiGateway",
            handler=self.func,
            proxy=True
        )

        table.grant_write_data(self.func)

🗣️ Yukkuri Commentary

Reimu: Lambda with DynamoDB… feels legit.
Marisa: Yes, true serverless vibes.
Reimu: No servers to maintain!
Marisa: Only feelings to maintain.


4.4 Define DynamoDB Table

from aws_cdk import aws_dynamodb as dynamodb

class DatabaseStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        self.table = dynamodb.Table(
            self, "VisitTable",
            partition_key={"name": "id", "type": dynamodb.AttributeType.STRING}
        )

🗣️ Yukkuri Commentary

Reimu: So every visitor gets stored?
Marisa: Yes. We remember EVERYTHING.
Reimu: That's creepy but… scalable?


4.5 Wiring Everything Together

App Entry

app.py

from aws_cdk import App
from infrastructure.web_stack import WebStack
from infrastructure.db_stack import DatabaseStack
from infrastructure.api_stack import ApiStack

app = App()

db = DatabaseStack(app, "DatabaseStack")
web = WebStack(app, "WebStack")
api = ApiStack(app, "ApiStack", table=db.table)

app.synth()

🗣️ Yukkuri Commentary

Reimu: So this connects everything?
Marisa: Yes. This is the “glue.”
Reimu: Glue like in AWS Glue?
Marisa: Don't summon those horrors yet. Too early.


4.6 cdk synth, cdk deploy, Review CloudFormation

Commands

cdk synth
cdk diff
cdk deploy --all

Go check AWS Console:

  • ✅ S3 bucket created
  • ✅ CloudFront distribution deployed
  • ✅ API Gateway URL printed
  • ✅ DynamoDB table created

Test API:

curl "$(cdk output ApiStack.ApiEndpoint)/?name=Reimu"

🗣️ Yukkuri Commentary

Reimu: My cloud app lives!
Marisa: It breathes digital air.
Reimu: Fear me, mere mortals! I deploy serverless now!
Marisa: Calm down, you’re still on free tier.


4.7 Cleanup / Teardown

cdk destroy --all

Also empty S3 deployment buckets if deletion fails.


🗣️ Yukkuri Commentary

Reimu: Important step: delete things so AWS doesn't eat my wallet.
Marisa: True. The cloud giveth and the cloud taketh your credit card.


✅ End of Chapter Summary

You built:

  • Static hosting in S3 + CloudFront
  • Lambda REST API + API Gateway
  • DynamoDB persistence
  • Full CDK stack integration
  • Deploy + test + cleanup cycles

This was a real cloud app — congratulations!

Chapter 5: Hands-On Project II

Multi-Stack Architecture & Networking

With Yukkuri Reimu & Marisa Commentary

In this chapter, we expand our AWS CDK skills into networking and multi-stack design.

We will build:

  • A VPC with public/private subnets
  • Security Groups
  • A shared infrastructure stack
  • A service stack that consumes shared resources
  • Cross-stack outputs/imports
  • Tags and Aspects
  • Multi-region/multi-account notes
  • Deploy and validate everything

5.1 Why Multiple Stacks?

Motivation

Reason Benefit
Organizational boundaries Separate team ownership
Security Least privilege isolation
Performance Parallel deploys & modular updates
Scalability Manage large infrastructure
Reusability Core/shared infra stack

Think microservices, but for infrastructure.


🗣️ Yukkuri Commentary

Reimu: So stacks are like “microcloud services”?
Marisa: Yes! Micro-infra! Small pieces, loosely coupled!
Reimu: And bills distributed evenly?
Marisa: laughs in CloudWatch charges


5.2 Defining a VPC, Subnets, Security Groups

VPC & Subnets

infrastructure/network_stack.py

from aws_cdk import (
    Stack,
    aws_ec2 as ec2,
)
from constructs import Construct

class NetworkStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        self.vpc = ec2.Vpc(
            self, "AppVpc",
            max_azs=2,
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    name="Public",
                    subnet_type=ec2.SubnetType.PUBLIC
                ),
                ec2.SubnetConfiguration(
                    name="Private",
                    subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS
                ),
            ]
        )

Security Group

self.api_sg = ec2.SecurityGroup(
    self, "ApiSecurityGroup",
    vpc=self.vpc,
    allow_all_outbound=True
)

self.api_sg.add_ingress_rule(
    ec2.Peer.any_ipv4(), ec2.Port.tcp(443),
    "Allow HTTPS"
)

🗣️ Yukkuri Commentary

Reimu: Wait, network configs… that means complexity approaching?
Marisa: Yes, networking is where souls are tested.
Reimu: But we have CDK magic!
Marisa: True. Less pain — still some pain.


5.3 Shared Infra Stack vs Service-Specific Stack

We separate infrastructure:

Stack Purpose
NetworkStack VPC + SGs
ServiceStack Lambda + API that uses VPC

5.4 Inter-Stack References (Exports/Imports)

Service Stack

infrastructure/service_stack.py

from aws_cdk import (
    Stack,
    aws_lambda as _lambda,
    aws_apigateway as apigw,
)
from constructs import Construct

class ServiceStack(Stack):
    def __init__(self, scope: Construct, id: str, vpc, api_sg, **kwargs):
        super().__init__(scope, id, **kwargs)

        self.func = _lambda.Function(
            self, "VpcLambda",
            runtime=_lambda.Runtime.PYTHON_3_9,
            handler="handler.handler",
            code=_lambda.Code.from_asset("lambda"),
            vpc=vpc,
            security_groups=[api_sg]
        )

        self.api = apigw.LambdaRestApi(
            self, "VpcApi",
            handler=self.func
        )

App Entry

app.py

from aws_cdk import App
from infrastructure.network_stack import NetworkStack
from infrastructure.service_stack import ServiceStack

app = App()

net = NetworkStack(app, "NetworkStack")
ServiceStack(app, "ServiceStack",
    vpc=net.vpc,
    api_sg=net.api_sg
)

app.synth()

🗣️ Yukkuri Commentary

Reimu: So we pass resources like sharing noodles?
Marisa: Exactly — but you can isolate packets instead of ramen.
Reimu: Cloud ramen security!
Marisa: Delicious. Secure. Scalable.


5.5 Multi-Region / Multi-Account Considerations

Basic Practice

from aws_cdk import Environment

ServiceStack(app, "ServiceStack",
    env=Environment(
        account="123456789012",
        region="us-east-1"
    ),
    vpc=net.vpc,
    api_sg=net.api_sg
)

Notes

  • Bootstrap each account/region
  • Cross-region reference limitations
  • Prefer messaging (SNS/SQS/EventBridge) for cross-region architectures

🗣️ Yukkuri Commentary

Reimu: Deploy to multiple regions? Sounds fancy.
Marisa: Fancy and terrifying. Like multi-dimensional cloud chess.
Reimu: I will practice in one region first…


5.6 Aspects for Tagging & Validation

from aws_cdk import Tags, Aspects

Tags.of(app).add("Project", "CloudTraining")
Tags.of(app).add("Environment", "Dev")

Custom Aspects Example

from constructs import IConstruct

class NoPublicIngressAspect:
    def visit(self, node: IConstruct):
        if isinstance(node, ec2.SecurityGroup):
            # enforce no public ingress here
            pass

Aspects.of(app).add(NoPublicIngressAspect())

🗣️ Yukkuri Commentary

Reimu: Tag everything?
Marisa: Yes. Tags are love. Tags are billing clarity.
Reimu: Ah yes. Avoid “mystery charges.”
Marisa: Never anger the billing gods.


5.7 Deploy & Verify

Deploy

cdk synth
cdk diff
cdk deploy --all

Verify

  • VPC created
  • Subnets created
  • Security group configured
  • Lambda in VPC
  • API works
  • CloudFormation stacks separated

Cleanup

cdk destroy --all

🗣️ Yukkuri Commentary

Reimu: Everything deployed! It lives!
Marisa: It breathes VPC air now.
Reimu: And then we destroy it?
Marisa: Yes. Destruction is cloud hygiene.


✅ Chapter Summary

You learned how to:

  • Architect multiple stacks
  • Build VPC networks & security groups
  • Separate shared vs service stacks
  • Pass resources between stacks
  • Plan for multi-region & multi-account
  • Use Aspects and tagging
  • Deploy + verify infrastructure

You are now a CDK networking practitioner.

Chapter 6: Hands-On Project III — Serverless Event-Driven Application

In this chapter, you will build an event-driven system using:

  • SQS OR SNS OR EventBridge
  • Lambda consumers
  • DynamoDB persistence
  • Step Functions for orchestration (optional path)
  • CloudWatch logging & metrics
  • Cost & scaling considerations

6.1 Overview of Serverless Patterns

Event-driven architectures use events to trigger compute.

Pattern Example Purpose
Pub/Sub SNS → multiple Lambdas Fan-out
Queue processing SQS → Lambda Decoupling, retries
Event bus EventBridge SaaS integration, routing
State machines Step Functions Complex workflows
Streams Kinesis / Firehose → Lambda Real-time data

🗣️ Yukkuri Commentary

Reimu: So serverless is like summoning compute only when needed?
Marisa: Exactly. Like a ninja — appears, executes, vanishes, leaves no traces.
Reimu: Except CloudWatch logs.
Marisa: True. Ninjas log everything in CloudWatch. For billing.


6.2 Create SQS Queue + SNS Topic + EventBridge Bus

Imports

from aws_cdk import (
    Stack,
    aws_sqs as sqs,
    aws_sns as sns,
    aws_sns_subscriptions as subs,
    aws_events as events,
    aws_events_targets as targets,
)
from constructs import Construct

Define Queue / Topic / Event Bus

class MessagingStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        self.queue = sqs.Queue(self, "AppQueue")

        self.topic = sns.Topic(self, "AppTopic")
        self.topic.add_subscription(
            subs.SqsSubscription(self.queue)
        )

        self.bus = events.EventBus(self, "AppEventBus")

Architecture created:

SNS → SQS → Lambda
     ↘ EventBridge

🗣️ Yukkuri Commentary

Reimu: SNS fans out events like a gossip network!
Marisa: Yes, SNS is cloud rumor system.
Reimu: And SQS makes rumors wait in a line.
Marisa: FIFO gossip queue — premium drama.


6.3 Lambda Consumers Writing to DynamoDB

Lambda Code

lambda/worker.py

import json, boto3, os
ddb = boto3.resource("dynamodb").Table(os.environ["TABLE_NAME"])

def handler(event, context):
    for record in event["Records"]:
        body = json.loads(record["body"])
        ddb.put_item(Item={"id": body["id"], "event": body})
    return "OK"

Define Table + Lambda + Event Trigger

from aws_cdk import (
    aws_lambda as _lambda,
    aws_lambda_event_sources as sources,
    aws_dynamodb as dynamodb,
)

class ProcessingStack(Stack):
    def __init__(self, scope: Construct, id: str, queue, **kwargs):
        super().__init__(scope, id, **kwargs)

        table = dynamodb.Table(
            self, "EventsTable",
            partition_key={"name": "id", "type": dynamodb.AttributeType.STRING}
        )

        func = _lambda.Function(
            self, "QueueWorker",
            runtime=_lambda.Runtime.PYTHON_3_9,
            handler="worker.handler",
            code=_lambda.Code.from_asset("lambda"),
            environment={"TABLE_NAME": table.table_name}
        )

        func.add_event_source(sources.SqsEventSource(queue))
        table.grant_write_data(func)

🗣️ Yukkuri Commentary

Reimu: Messages come in, Lambda writes to DB… magical pipeline!
Marisa: It’s a conveyor belt of events.
Reimu: Like a sushi belt, but JSON flavored.
Marisa: And DynamoDB eats everything.


6.4 Step Functions (optional advanced)

State Machine example

from aws_cdk import aws_stepfunctions as sfn
from aws_cdk import aws_stepfunctions_tasks as tasks

task = tasks.LambdaInvoke(self, "ProcessEvent", lambda_function=func)

definition = task.next(sfn.Succeed(self, "Done"))

sfn.StateMachine(self, "EventProcessor",
    definition=definition
)

Optional: Kinesis / Firehose for streaming pipeline.


🗣️ Yukkuri Commentary

Reimu: So Step Functions orchestrate many Lambdas?
Marisa: Yes. It’s the puppet master.
Reimu: Cloud puppet theater!
Marisa: With JSON strings instead of strings.


6.5 Monitoring: CloudWatch Logs, Metrics, Alerts

Enable metrics & alarms:

from aws_cdk import aws_cloudwatch as cw

cw.Alarm(self, "QueueDepthAlarm",
    metric=queue.metric_approximate_number_of_messages_visible(),
    threshold=100,
    evaluation_periods=1
)

View:

  • Lambda logs in CloudWatch
  • SQS queue length
  • DynamoDB throttles
  • Step Function execution history

🗣️ Yukkuri Commentary

Reimu: Monitor logs! Understand errors!
Marisa: Logs are truth. Metrics are destiny.
Reimu: Alert me only when critical.
Marisa: Or when lonely, like “Hey, I missed you. Queue is empty.”


6.6 Cost & Scaling Considerations

Key Factors

Resource Pricing Trigger
Lambda Execution time & requests
SQS API calls & data
SNS Requests & fan-out traffic
DynamoDB RCU/WCU or On-Demand
Step Functions State transitions

Tips

  • Use on-demand DynamoDB until stable traffic
  • Tune Lambda memory (affects speed)
  • Dead Letter Queues (DLQ) for failure safety
  • SQS batch size improves efficiency
sources.SqsEventSource(queue, batch_size=10)

🗣️ Yukkuri Commentary

Reimu: Serverless seems cost-effective.
Marisa: Yes… until you forget to turn off debug logs.
Reimu: CloudWatch bill trauma incoming.
Marisa: We cry, then optimize.


✅ Chapter Summary

You built:

  • Event-driven queue + topic + event bus
  • Lambda processing pipeline
  • DynamoDB persistence
  • Optional Step Functions workflow
  • Monitoring alarms
  • Cost strategies

You now wield cloud automation power.

Chapter 7: Testing, CI/CD and Quality of CDK Apps

Infrastructure deserves the same rigor as application code. In this chapter, we cover:

  • Testing CDK constructs
  • Snapshot tests & E2E flows
  • CI/CD pipelines (GitHub Actions & CodePipeline)
  • Linting & type checking
  • Handling drift & stack lifecycle policies

7.1 Unit Testing CDK Constructs (pytest + CDK Assertions)

Install dependencies:

pip install pytest aws-cdk-lib constructs
pip install aws-cdk.assertions

Example Stack

from aws_cdk import Stack, aws_s3 as s3
from constructs import Construct

class DemoStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        s3.Bucket(self, "MyBucket",
            versioned=True,
            encryption=s3.BucketEncryption.S3_MANAGED
        )

Test with CDK Assertions

test_demo.py

import aws_cdk as cdk
from aws_cdk import assertions
from demo.demo_stack import DemoStack

def test_bucket_created():
    app = cdk.App()
    stack = DemoStack(app, "TestStack")
    template = assertions.Template.from_stack(stack)

    template.has_resource_properties("AWS::S3::Bucket", {
        "VersioningConfiguration": {"Status": "Enabled"}
    })

Run:

pytest

🗣️ Yukkuri Commentary

Reimu: Testing infrastructure feels… weird?
Marisa: But glorious. We prevent future cloud sadness.
Reimu: And AWS mistakes are expensive sadness.
Marisa: Unit tests = cost protection charms.


7.2 Snapshot Tests, Integration Tests, E2E Tests

Snapshot Test Example

def test_snapshot():
    app = cdk.App()
    stack = DemoStack(app, "SnapshotStack")
    template = assertions.Template.from_stack(stack)

    template.to_json()  # saved and compared automatically

Stores JSON snapshot in repo. Change detected? → CI fails = infra review time.

Integration Test Strategy

  • Deploy to staging
  • Validate resource endpoints (Lambda/API)
  • Assert IAM roles exist

End-to-End Test Example (Concept)

curl https://my-api.example.com/hello | grep "Hello"

Combine with pytest + boto3 for automated checks.


🗣️ Yukkuri Commentary

Reimu: Snapshots catch “oops, I didn't mean to wipe production,” right?
Marisa: Exactly. A safety net against accidental chaos.
Reimu: So like a cloud parachute?
Marisa: More like airbag for your career.


7.3 CI/CD Pipelines

GitHub Actions Example: deploy.yml

name: CDK Deploy

on:
  push:
    branches: [ "main" ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.9"

      - name: Install CDK
        run: npm install -g aws-cdk

      - name: Install Python deps
        run: |
          python -m venv .venv
          source .venv/bin/activate
          pip install -r requirements.txt

      - name: CDK Deploy
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: cdk deploy --all --require-approval never

CDK CodePipeline Example

from aws_cdk import aws_codepipeline as pipeline
from aws_cdk import aws_codepipeline_actions as actions

(Full pipeline in Appendix)


🗣️ Yukkuri Commentary

Reimu: Auto-deploy cloud changes when I push code? Heaven!
Marisa: Yes, but beware — automated explosions are also faster.
Reimu: Truly the power and terror of DevOps.
Marisa: Pipelines are anime transformation sequences for infrastructure.


7.4 Linting & Type Checking (mypy)

Install tools:

pip install mypy black flake8

Type Check Example

mypy src/

mypy-friendly CDK pattern

from typing import Optional
bucket: Optional[s3.Bucket] = None

Lint & Format

flake8
black .

🗣️ Yukkuri Commentary

Reimu: Types in Python?
Marisa: Yes, we can pretend it’s TypeScript for a day.
Reimu: My code looks smarter already.
Marisa: Clean CDK code sparks joy.


7.5 Handling Drift, Stack Updates, Deletion Policies

Detect Drift

cdk diff

Or CloudFormation console → Drift Detection.

Prevent Data Loss

from aws_cdk import RemovalPolicy

bucket = s3.Bucket(self, "DataBucket",
    removal_policy=RemovalPolicy.RETAIN
)

Update Strategies

Technique Use case
cdk diff Review changes before deploy
Change sets Manual approvals
Phased stack replacement Big infra upgrades

🗣️ Yukkuri Commentary

Reimu: Drift sounds spooky.
Marisa: Yes. Cloud entropy. Infra chaos creeping in.
Reimu: And deletion policy stops accidental wipeouts?
Marisa: Yes. Buckets stay. Your sanity stays.


✅ Chapter Summary

You learned to:

  • Unit-test CDK stacks with pytest & assertions
  • Snapshot and E2E test infra
  • Build CI/CD pipelines with GitHub Actions
  • Use mypy + lint tools for quality
  • Detect drift & enforce safe removals

You now wield both cloud power and discipline.

Chapter 8: Advanced Patterns & Best Practices

In this chapter, we elevate your CDK skills from builder to architect. We will focus on scalable, maintainable, secure CDK patterns.


8.1 Construct Library Design: Reusable Constructs

Custom constructs let you package infrastructure logic like reusable software modules.

Folder structure

infra/
  constructs/
    __init__.py
    network_construct.py
  stacks/
    app_stack.py

Example: Custom Construct

constructs/network_construct.py

from constructs import Construct
from aws_cdk import aws_ec2 as ec2

class NetworkConstruct(Construct):
    def __init__(self, scope: Construct, id: str):
        super().__init__(scope, id)

        self.vpc = ec2.Vpc(
            self, "Vpc",
            max_azs=2,
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    name="Private",
                    subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS
                )
            ]
        )

Using the construct

class AppStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)
        network = NetworkConstruct(self, "Network")

🗣️ Yukkuri Commentary

Reimu: Constructs are like making Lego pieces yourself?
Marisa: Exactly. But these Legos deploy servers.
Reimu: And mistakes deploy invoices.
Marisa: Yes. Architect responsibly.


8.2 Architecture Patterns

Microservices

Each service = its own stack + shared services stack.

SharedInfraStack  -> VPC, IAM, Monitoring
UserServiceStack
OrderServiceStack
PaymentServiceStack

Domain-Driven Stacks

Group by business domain, not AWS service.

Shared Infra Stack

Example resources:

  • VPC
  • Database clusters
  • Observability stack
  • KMS keys, IAM roles

🗣️ Yukkuri Commentary

Reimu: Microservices can become micro-chaos.
Marisa: True. Microservices without strategy = maximum pain.
Reimu: So CDK helps organize the cloud dojo?
Marisa: Yes. Structure before scale.


8.3 Infra Modularization and Versioning

Requirements file pinned

requirements.txt

aws-cdk-lib==2.91.0
constructs>=10.0.0,<11.0.0

Version catalog for constructs

Define internal version constant:

MODULE_VERSION = "1.3.0"

Tag deployments:

git tag v1.3.0

Publish to internal artifact repo → optional.


🗣️ Yukkuri Commentary

Reimu: Versioning infra feels like managing spellbooks.
Marisa: Yes, infra magic evolves — version your power.
Reimu: No rogue upgrades allowed!
Marisa: Only responsible sorcery.


8.4 Security & Compliance

IAM Least Privilege

table.grant_read_write_data(lambda_fn)
# NOT lambda_fn.add_to_role_policy(...)

Prefer grant* helpers (safer, scoped policies).

Tagging

from aws_cdk import Tags
Tags.of(self).add("Owner", "platform-team")
Tags.of(self).add("Environment", "prod")

Monitoring

  • CloudWatch dashboards
  • Alarms for errors & latency
  • Audit with AWS Config
  • Security Hub / IAM Access Analyzer

🗣️ Yukkuri Commentary

Reimu: Cloud security is serious business.
Marisa: Yes. The cloud has ninjas — and auditors.
Reimu: Least privilege or your wallet cries?
Marisa: Yes. And compliance demons appear.


8.5 Cost Optimization & Cleanup

S3 Lifecycle rules

s3.Bucket(self, "Logs",
    lifecycle_rules=[s3.LifecycleRule(
        expiration=Duration.days(30)
    )]
)

DynamoDB On-Demand

billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST

Turn on Lambda concurrency limits

reserved_concurrent_executions=10

🗣️ Yukkuri Commentary

Reimu: Optimize or perish?
Marisa: Cloud economics is battle strategy.
Reimu: Money saved = more ramen.
Marisa: Ramen-driven cloud design.


8.6 Anti-patterns & Pitfalls

Anti-pattern Better Way
Too many tiny stacks Group by domain
Huge monolithic stack Domain boundaries
Broad IAM policies grant_read_write_data()
Hard-coding env Use context, env vars
No lifecycle rules S3 grows forever
Ignoring drift cdk diff, config rules

🗣️ Yukkuri Commentary

Reimu: What happens if we ignore these warnings?
Marisa: Your infra becomes a cursed spaghetti shrine.
Reimu: Horrors beyond human comprehension.
Marisa: And billing department cries blood.


✅ Chapter Summary

You learned:

  • How to build reusable constructs
  • Microservices / domain-driven infra patterns
  • Infra versioning & modularity
  • Security, IAM, tagging, monitoring
  • Cost control strategies
  • Dangerous anti-patterns to avoid

You now think like a Cloud Architect.

Chapter 9: Operating CDK in Production

At this stage, you are ready for real-world operations. This chapter focuses on running CDK apps in production environments:

  • Environment management
  • Multi-account setups
  • Monitoring & observability
  • Troubleshooting CloudFormation states
  • Upgrading CDK
  • Future CDK ecosystem

9.1 Managing Multiple Environments (dev, staging, prod)

Strategies

Pattern Description
Separate stacks per env DevStack, StagingStack, ProdStack
Context parameters cdk deploy -c env=prod
Config files cdk.context.json, YAML env config
Parameter Store / Secrets Manager External config

Example using context

cdk deploy -c env=prod
env = self.node.try_get_context("env")
bucket_name = f"my-app-{env}"

s3.Bucket(self, "AppBucket", bucket_name=bucket_name)
  • dev / qa = sandbox
  • staging = pre-production
  • prod = protected account

🗣️ Yukkuri Commentary

Reimu: So each environment gets its own world?
Marisa: Yes. Multiverse cloud strategy.
Reimu: And prod is sacred ground?
Marisa: Touch prod only with clean commits and pure heart.


9.2 Multi-Account AWS + SSO

AWS Organizations & SSO

  • Separate accounts for security boundaries
  • AWS SSO (IAM Identity Center) for centralized login
  • Deploy through IAM roles instead of static keys

CDK Environment Config

from aws_cdk import Environment

prod_env = Environment(
    account="123456789012",
    region="us-east-1"
)

Assume Role Deployment Example

GitHub Actions:

- name: Assume role
  uses: aws-actions/configure-aws-credentials@v2
  with:
    role-to-assume: arn:aws:iam::123456789012:role/CDKDeployRole
    aws-region: us-east-1

🗣️ Yukkuri Commentary

Reimu: Multi-account sounds complex...
Marisa: It is. But so is rebuilding prod after an accident.
Reimu: So isolation = survival.
Marisa: Exactly — cloud Darwinism.


9.3 Monitoring & Observability

What to monitor

Component Metric
Lambda Errors, duration, concurrency
API Gateway 5xx, latency
DynamoDB Throttles, capacity
SQS Queue depth
CloudFront Cache hit rate

CDK CloudWatch Dashboard

from aws_cdk import aws_cloudwatch as cw

cw.Dashboard(self, "AppDashboard")

Add metrics:

dashboard.add_widgets(
    cw.GraphWidget(
        title="Lambda Errors",
        left=[fn.metric_errors()]
    )
)

🗣️ Yukkuri Commentary

Reimu: If we don't watch it, it breaks?
Marisa: It breaks even if you watch it — but you notice faster.
Reimu: Observability is pain awareness.
Marisa: Wisdom comes from logs.


9.4 Troubleshooting CDK Deployments

CloudFormation Error Checklist

Issue Fix
Failed create/update Check events tab
Insufficient permissions IAM role/assume role policies
Stuck rollback Delete stack resources manually
Resource already exists Import or rename
Dependency loops Consolidate or split resources

How to debug

Terminal

cdk deploy -v

CloudFormation Console

  • Events tab
  • Nested stack failures
  • IAM role trust issues

🗣️ Yukkuri Commentary

Reimu: CloudFormation failed! Panic?
Marisa: No. Panic after reading logs.
Reimu: Why does rollback feel like judgement day?
Marisa: Because it is. AWS gods are cruel and just.


9.5 Upgrading CDK versions safely

Strategy

  1. Pin version in requirements.txt
  2. Upgrade incrementally
  3. cdk diff before deploying
  4. Test in dev/staging first

Upgrade example

aws-cdk-lib==2.92.0 → aws-cdk-lib==2.100.0

Use release notes → https://github.com/aws/aws-cdk/releases


🗣️ Yukkuri Commentary

Reimu: Upgrades bring new powers!
Marisa: And new bugs. Read release notes like sacred scrolls.
Reimu: Fearful respect for version numbers.
Marisa: A true cloud monk.


9.6 Future of CDK

Tech Concept
CDK for Terraform (CDKTF) CDK syntax → Terraform engine
CDK8s Kubernetes manifests in code
Projen Project config as code
Serverless Cloud (future tools) Higher level abstractions

Example CDK8s

from cdk8s import Chart
from constructs import Construct
from imports.k8s import KubeDeployment

class AppChart(Chart):
    def __init__(self, scope: Construct, id: str):
        super().__init__(scope, id)

        KubeDeployment(self, "app",
            spec={"replicas": 2, "template": {...}}
        )

🗣️ Yukkuri Commentary

Reimu: So CDK is not just for AWS?
Marisa: Correct. CDK is spreading like cloud bamboo.
Reimu: Infrastructure everywhere.
Marisa: Code conquers configuration.


✅ Chapter Summary

You can now:

  • Manage dev → staging → prod safely
  • Run CDK with multi-account + SSO
  • Monitor real workloads
  • Debug CloudFormation issues
  • Upgrade CDK versions safely
  • Understand the future landscape (CDKTF, CDK8s)

You are now ready for production-grade AWS CDK.

Appendix A — CDK CLI Commands Cheat Sheet

Essential Commands

cdk init app --language python     # create a new CDK project
cdk synth                          # generate CloudFormation template
cdk diff                           # compare local vs deployed stack
cdk deploy                         # deploy a stack
cdk deploy --all                   # deploy all stacks
cdk destroy                        # tear down stack
cdk list                           # list stacks in app
cdk context                        # display cached context
cdk doctor                         # diagnose environment
cdk bootstrap                      # prepare env for CDK

Useful flags

cdk deploy --require-approval never
cdk deploy -c env=prod
cdk diff --verbose

🗣️ Yukkuri Commentary

Reimu: So cdk synth is the “see the future” command?
Marisa: Yes. And cdk diff is “spot disaster before it happens.”
Reimu: And cdk destroy is…
Marisa: Order 66 for cloud resources. Use wisely.


Appendix B — Python & AWS Construct Library Reference

Common Imports

from aws_cdk import (
    App, Stack,
    Duration, RemovalPolicy,
    aws_s3 as s3,
    aws_lambda as _lambda,
    aws_dynamodb as dynamodb,
    aws_ec2 as ec2,
    aws_apigateway as apigw,
    aws_sqs as sqs,
    aws_sns as sns,
    aws_events as events,
    aws_events_targets as targets,
)
from constructs import Construct

CDK Patterns

Bucket w/ lifecycle + encryption

s3.Bucket(self, "Logs",
    encryption=s3.BucketEncryption.S3_MANAGED,
    lifecycle_rules=[s3.LifecycleRule(
        expiration=Duration.days(30)
    )]
)

Lambda + env vars

_lambda.Function(
    self, "Handler",
    runtime=_lambda.Runtime.PYTHON_3_9,
    handler="app.handler",
    code=_lambda.Code.from_asset("lambda"),
    environment={"STAGE": "prod"}
)

VPC + SG

vpc = ec2.Vpc(self, "AppVpc", max_azs=2)
sg = ec2.SecurityGroup(self, "AppSG", vpc=vpc)

🗣️ Yukkuri Commentary

Reimu: This is like Pokémon stats for AWS resources.
Marisa: Yes — collect them all, but only deploy with intention.
Reimu: No random Lambda spamming?
Marisa: Unless you enjoy mystery bills.


Appendix C — Migration Guide: CDK v1 → v2

Key Differences

CDK v1 CDK v2
Many packages aws-cdk-lib only
@aws-cdk/core constructs pkg
Mixed stability Stable API by default

Migration Steps

  1. Upgrade CLI
npm install -g aws-cdk@latest
  1. Update dependencies
aws-cdk-lib>=2.0.0
constructs>=10.0.0,<11.0.0
  1. Replace imports
# old
from aws_cdk import core

# new
from aws_cdk import App, Stack
from constructs import Construct
  1. Remove deprecated APIs
  2. Test with cdk diff
  3. Deploy to dev → staging → prod

🗣️ Yukkuri Commentary

Reimu: Migrating is scary!
Marisa: Yes, like updating magical spell formulas.
Reimu: What if something explodes?
Marisa: That's why we use test environments and snacks. Snacks help.


Appendix D — Resources & Links

Official Docs

Examples

Community

  • AWS CDK Slack
  • Reddit r/aws
  • Stack Overflow tag aws-cdk
  • AWS Builders Discord

Learning


🗣️ Yukkuri Commentary

Reimu: So many resources!
Marisa: Yes, knowledge is infinite. Time is not.
Reimu: So copy-paste wisely.
Marisa: Copy-paste, then understand — the cloud way.


Appendix E — Glossary of Terms

Term Meaning
CDK Cloud Development Kit
Construct Reusable cloud component
Stack CloudFormation stack
App CDK program entry
Synthesis Convert CDK → CloudFormation template
Drift Deployed infra differs from code
Least privilege Minimal IAM permissions
Bootstrap Prepare AWS env for CDK
IaC Infrastructure as Code
Decoupling Design components independently
On-demand Pay-per-use pricing mode
Observability Logs + metrics + traces

🗣️ Yukkuri Commentary

Reimu: Glossary unlocked! Final boss defeated!
Marisa: Yes — you now speak the sacred language of the cloud.
Reimu: Time to ascend as Cloud Priestess?
Marisa: Go forth and deploy — and try not to awaken Billing-kun.


🎉 Book Complete!

You now understand:

  • CDK from basics → production
  • Multi-stack patterns
  • Serverless workflows
  • CI/CD practices
  • Cost + security strategies
  • Migration and future CDK roadmap