In this project, I try to gain deep and hands-on knowledge of architecting application in AWS by using CDK to implement popular architectural patterns in AWS.
Discover AWS patterns in folder patterns:
Datastore / S3:
-
s3-polished-configuration: S3 with encryption, versioning enabled, lifecycle rule, data archiver with Glacier -
s3-events-notification: S3 → SNS → SQS → SQS (DLQ) -
s3-cross-region-replication: S3 → S3 (another region); Multi-region Access Point for S3 -
s3-static-website-cloudfront: S3 hosting a HTTPS static website, using CloudFront for global delivery -
s3-lambda-rekognition-dynamodb: image processing pipeline and metadata storage -
s3-behind-sftp: SFTP access to S3 using AWS Transfer -
s3-vectors-bucket: S3 Vector Bucket + Index for similarity search on food reviews -
s3-serverless-data-lake: S3 (Storage) → AWS Glue (Data Catalog/Crawler) → Amazon Athena
Datastore / Dynamodb:
-
dynamodb-global-database: Dynamodb Global Database (multi-write architecture) -
dynamodb-stream-lambda: Dynamodb → Dynamodb Stream → Lambda -
dynamodb-to-s3-zero-etl: Dynamodb → S3 with Zero-ETL -
dynamodb-kinesis-opensearch: Dynamodb & Stream → Kinesis Stream & Data Firehose → S3 | OpenSearch
Datastore / Elasticache:
-
elasticache-valkey-active-passive: ElastiCache Valkey replication group (1 primary + N replicas) -
elasticache-valkey-cluster: ElastiCache Valkey cluster mode enabled (N shards × M replicas) -
elasticache-valkey-serverless: ElastiCache Valkey Serverless (auto-scaling, ECPU billing)
Datastore / RDS & Aurora Postgres:
-
rds-postgres: Multi-AZ failover (Hot Standby), automated backups, Secrets Manager, RDS Proxy -
rds-read-replicas: Async read replicas (same-region + cross-region) -
rds-readable-standbys: Multi-AZ with 2 readable standbys - synchronous replication, <35s failover -
rds-aurora-provisioned: Cloud Native PostgreSQL, writer + up to 15 readers, custom endpoints -
rds-aurora-serverless-v2: Aurora Serverless - ACU-based autoscaling, serverless + provisioned mix -
rds-aurora-global: Aurora Global Database - <1s cross-region replication, Write Forwarding -
rds-cdc-streaming: RDS → DMS CDC → Kinesis → Lambda — trigger actions on changes -
rds-redshift-zero-etl: Aurora → Redshift Zero-ETL — continuous replication to Redshift for analytics -
rds-opensearch: RDS → OpenSearch Ingestion → OpenSearch for full-text and vector search -
rds-data-lake: RDS → DMS CDC → S3 (Parquet) — cheap long-term storage and batch analytics via Athena
Datastore / OpenSearch:
-
opensearch-provisioned: Managed OpenSearch domain - single-node to Multi-AZ cluster -
opensearch-serverless: OpenSearch Serverless collection - OCU-based autoscaling
Infra / Containers on AWS:
-
elastic-container-registry: ECR repository provisioning, Docker image build & push -
app-runner: App Runner — fully managed, source-to-URL container hosting -
ecs-fargate-alb: ECS Fargate + ALB — serverless containers behind Application Load Balancer -
ecs-fargate-apigw: ECS Fargate + API Gateway HTTP API + VPC Link -
ecs-ec2-alb: ECS on EC2 (Spot) + ALB — self-managed container instances behind load balancer -
lambda-container: Lambda container image + Function URL — serverless per-request execution -
ec2s-behind-alb: Auto Scaling Group of EC2s running Docker behind ALB -
eks-fargate: EKS Fargate — Kubernetes control plane + serverless pods, no node management -
one-ec2: Single EC2 instance running Docker, public-facing
Infra / Others:
-
vpc-subnets: VPC 3-tier subnet layout (public/private/isolated) across 3 AZs, NAT Gateways -
ssm-bastion: EC2 instance for SSM Session Manager - secure port forwarding to isolated resources without SSH -
event-bridge-lambda-job: Lightweight job with event bridge triggering lambda function using cron schedule -
msk-lambda: Kafka cluster setup via Amazon Managed Streaming for Kafka (MSK), Lambda consumer -
waf-shield-ddos-protection: AWS WAF + Shield for DDoS protection on CloudFront -
sagemaker-pipeline: Building an end-to-end ML pipeline with AWS SageMaker and CDK -
glue-etl-job: AWS Glue ETL job that processes and transforms data in S3 to different format -
vpc-endpoints-privatelink: VPC Gateway endpoints (S3, DynamoDB) + Interface endpoints (SQS, ECR)
Infra / Inter-service communications:
-
sqs-lambda: SQS → Lambda with DLQ and batch processing -
step-functions-workflow: Step Functions for serverless statemachine orchestration of multiple Lambdas -
eventbridge-sns-fanout: EventBridge rule with content filtering → SNS → multiple SQS subscribers -
apigw-lambda-cognito: API Gateway REST API + Lambda + Cognito User Pool authorizer -
apigw-websocket: API Gateway WebSocket API + Lambda + DynamoDB connection tracking
| Command | Description |
|---|---|
pnpm run build |
Compile TypeScript to JS |
pnpm run watch |
Watch for changes and compile |
pnpm run test |
Run Jest unit tests |
npx cdk synth |
Emit synthesized CloudFormation template |
npx cdk diff |
Compare deployed stack with current state |
npx cdk deploy |
Deploy stack to your default AWS account/region |
npx cdk destroy |
Tear down a deployed stack |
- Node.js (v18+)
- pnpm package manager
- AWS CLI configured with valid credentials (
aws configure) - AWS CDK CLI (included via
npx cdk)
pnpm installCDK automatically resolves CDK_DEFAULT_ACCOUNT and CDK_DEFAULT_REGION from your AWS CLI profile (aws configure). To target a specific region: export CDK_DEFAULT_REGION=eu-central-1
bin/cdk.ts # Entry point — registers all CDK stacks
patterns/<name>/
├── stack.ts # CDK Stack class (or stack_step*.ts for multi-step patterns)
├── README.md # Pattern-specific notes
├── cloud_formation.yaml # Synthesized CloudFormation output
├── demo_server.ts # (Optional) Express server to demo the pattern
└── demo_requests.http # (Optional) HTTP requests for the demo server
utils/
└── stackoutput.ts # getStackOutputs(stackName) — discovers deployed resources at runtime
- Create
patterns/<name>/stack.ts— extendcdk.Stack, export a stack name constant, and useCfnOutputfor key resource IDs/ARNs - Register the stack in
bin/cdk.ts - (Optional) Add
demo_server.tsusinggetStackOutputs()to discover resources at runtime - Add a
README.mdin the pattern folder - Synthesize the template:
npx cdk synth <StackName> > patterns/<name>/cloud_formation.yaml
AWS_REGION=eu-central-1 npx ts-node patterns/<name>/demo_server.tsDemo servers use getStackOutputs() from utils/stackoutput.ts to discover deployed resource names and ARNs at runtime — no hardcoding needed. Deploy the pattern stack first, then start the server.
CDK organizes cloud resources into three levels of abstraction called constructs:
| Level | Name | What it is | Example |
|---|---|---|---|
| L1 | CFN Resources | 1:1 mapping to CloudFormation resources. Prefixed with Cfn. No defaults — you configure every property yourself. |
CfnBucket, CfnFunction |
| L2 | Curated Constructs | AWS-vetted wrappers around L1. Provide sensible defaults, helper methods (e.g., bucket.grantRead(lambda)), and a higher-level API. Most of what you'll use day-to-day. |
s3.Bucket, lambda.Function |
| L3 | Patterns | Opinionated multi-resource compositions. Wire together several L2 constructs into a common architecture. | LambdaRestApi (API Gateway + Lambda), S3BucketDeployment (S3 + Lambda + Custom Resource) |
When to use which:
- Start with L2 — covers ~90% of cases with good defaults and grant helpers that auto-generate least-privilege IAM policies.
- Drop to L1 when you need a property that L2 doesn't expose yet (use
node.defaultChildto escape-hatch from L2 to L1). - Use L3 when a well-known pattern exists and you don't need to customize the wiring between resources.
Stage 1 — Environment setup (once per account/region)
npx cdk bootstrap— provisions the S3 bucket and IAM resources CDK needs to store assets (Lambda packages, templates) during deployment. Run once per AWS account + region before first deploy.
Stage 2 — Development
npx cdk ls— list all stacks defined in the app; confirms the code compiles and shows what's available to deploy.npx cdk synth <StackName>— compile your CDK code into a CloudFormation template (written tocdk.out/). Use this to inspect what will actually be deployed or catch errors early.
Stage 3 — Review
npx cdk diff <StackName>— compare your local code against what's currently deployed. Likegit difffor infrastructure — always run this before deploying to see exactly what will be added, changed, or deleted.
Stage 4 — Deploy
npx cdk deploy <StackName>— upload assets to the bootstrap bucket and apply the CloudFormation template to your AWS account.
Stage 5 — Teardown
npx cdk destroy <StackName>— delete the CloudFormation stack and all resources within it. Prompts for confirmation before deleting.
Note: All patterns use
removalPolicy: DESTROYandautoDeleteObjects: truefor easy cleanup. These settings are not production-safe.