DEV Community

Cover image for Deploying Real Infrastructure Easily (AWS CDK)
Germán Neironi
Germán Neironi

Posted on

Deploying Real Infrastructure Easily (AWS CDK)

You've probably heard about Infrastructure as Code. Maybe you've even written some CloudFormation YAML and felt your soul leave your body around line 847.

There's a better way.

AWS CDK (Cloud Development Kit) lets you define infrastructure using real programming languages - TypeScript, Python, Java, Go. No more YAML indentation nightmares. No more copy-pasting 200-line templates you found on Stack Overflow.

Let me show you how to go from zero to deploying real infrastructure in 10 minutes.

What is AWS CDK?

CDK is a framework that lets you define AWS resources using code. You write TypeScript (or Python, etc.), CDK converts it to CloudFormation, and deploys it.

Your Code (TypeScript) → CDK → CloudFormation → AWS Resources
Enter fullscreen mode Exit fullscreen mode

The magic: you get loops, conditionals, functions, type checking, and IDE autocomplete. Things that are painful or impossible in YAML.

Setup (2 minutes)

You need Node.js and AWS CLI configured. Then:

npm install -g aws-cdk
mkdir my-first-cdk && cd my-first-cdk
cdk init app --language typescript
Enter fullscreen mode Exit fullscreen mode

This creates a project structure:

my-first-cdk/
├── bin/
│   └── my-first-cdk.ts    # Entry point
├── lib/
│   └── my-first-cdk-stack.ts  # Your infrastructure
├── package.json
└── cdk.json
Enter fullscreen mode Exit fullscreen mode

Your First Stack (3 minutes)

Open lib/my-first-cdk-stack.ts. Let's create an S3 bucket with some sensible defaults:

import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';

export class MyFirstCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create an S3 bucket
    const bucket = new s3.Bucket(this, 'MyBucket', {
      versioned: true,
      encryption: s3.BucketEncryption.S3_MANAGED,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      removalPolicy: cdk.RemovalPolicy.DESTROY, // For dev only!
    });

    // Output the bucket name
    new cdk.CfnOutput(this, 'BucketName', {
      value: bucket.bucketName,
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

That's it. A secure, versioned S3 bucket in 15 lines of readable code.

The equivalent CloudFormation? Around 40 lines of YAML.

See What You're Deploying (1 minute)

Before deploying, you can see exactly what CloudFormation CDK will generate:

cdk synth
Enter fullscreen mode Exit fullscreen mode

And see the diff against your current AWS state:

cdk diff
Enter fullscreen mode Exit fullscreen mode

This shows you exactly what will be created, modified, or deleted. No surprises.

Deploy (2 minutes)

cdk bootstrap  # First time only, sets up CDK in your account
cdk deploy
Enter fullscreen mode Exit fullscreen mode

Watch your terminal. CDK creates a CloudFormation stack, provisions the resources, and shows you the outputs.

Done. You have a production-ready S3 bucket.

Why CDK Beats YAML

Let me show you the real power. Say you need 3 buckets for different environments:

const environments = ['dev', 'staging', 'prod'];

environments.forEach(env => {
  new s3.Bucket(this, `DataBucket-${env}`, {
    bucketName: `myapp-data-${env}-${this.account}`,
    versioned: env === 'prod', // Only version prod
    lifecycleRules: env !== 'prod' ? [{
      expiration: cdk.Duration.days(30), // Auto-cleanup non-prod
    }] : [],
  });
});
Enter fullscreen mode Exit fullscreen mode

Try doing that cleanly in YAML. I'll wait.

Real-World Pattern: Lambda + API Gateway

Here's something more practical - a serverless API:

import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigw from 'aws-cdk-lib/aws-apigateway';

// Create Lambda function
const handler = new lambda.Function(this, 'ApiHandler', {
  runtime: lambda.Runtime.NODEJS_18_X,
  code: lambda.Code.fromAsset('lambda'),
  handler: 'index.handler',
  timeout: cdk.Duration.seconds(30),
  memorySize: 256,
});

// Create API Gateway
const api = new apigw.RestApi(this, 'MyApi', {
  restApiName: 'My Service',
});

// Connect them
api.root.addMethod('GET', new apigw.LambdaIntegration(handler));
Enter fullscreen mode Exit fullscreen mode

Lambda function + API Gateway + all the IAM permissions, wired up correctly. In 20 lines.

Cost Optimization Patterns

One thing I've learned building CloudPruneAI: most cloud waste comes from missing simple configurations. CDK makes it easy to enforce good defaults:

// Always set log retention (CloudWatch logs grow forever by default!)
import * as logs from 'aws-cdk-lib/aws-logs';

const myFunction = new lambda.Function(this, 'MyFunction', {
  // ... config
  logRetention: logs.RetentionDays.TWO_WEEKS, // Don't pay for logs forever
});

// Always use lifecycle rules on S3
new s3.Bucket(this, 'LogsBucket', {
  lifecycleRules: [{
    transitions: [{
      storageClass: s3.StorageClass.INTELLIGENT_TIERING,
      transitionAfter: cdk.Duration.days(30),
    }],
    expiration: cdk.Duration.days(365),
  }],
});
Enter fullscreen mode Exit fullscreen mode

These patterns prevent the "silent cost creep" that hits most AWS accounts.

Destroying Resources

When you're done experimenting:

cdk destroy
Enter fullscreen mode Exit fullscreen mode

CDK removes everything it created. Clean.

Common Gotchas

1. Bootstrap once per account/region

cdk bootstrap aws://ACCOUNT_ID/REGION
Enter fullscreen mode Exit fullscreen mode

2. Stateful resources need care

By default, CDK protects databases and buckets from accidental deletion. For dev environments:

removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true, // For S3 buckets
Enter fullscreen mode Exit fullscreen mode

3. Use cdk diff before deploy

Always. It's saved me from many "oops" moments.

Next Steps

  1. Read constructs: Browse Construct Hub for pre-built patterns
  2. Try L2 constructs: Higher-level abstractions like ApplicationLoadBalancedFargateService that wire up 10+ resources in one line
  3. Organize with stages: Use cdk.Stage for multi-environment deployments

Resources


CDK changed how I think about infrastructure. It's not a config file you maintain - it's code you can test, refactor, and actually understand 6 months later.

Give it 10 minutes. Your future self will thank you.


What's your experience with IaC? Still using CloudFormation YAML, or have you moved to CDK/Terraform? Drop a comment below.

Top comments (0)