DEV Community

ak0047
ak0047

Posted on

Getting Started with IaC on AWS: Choosing Between CloudFormation, SAM, and CDK

Introduction

I’m currently building a React app.
In the past, I hosted it on S3 + CloudFront, so I thought I’d do the same this time. I went ahead and created the resources using the AWS Management Console, but then I caught myself thinking:

  • What settings did I use last time?
  • Did I misconfigure something this time?
  • Clicking through the console is such a hassle…

That’s when I decided to look into how to provision AWS resources with IaC (Infrastructure as Code).

In this post, I’ll walk through the main IaC tools available on AWS, compare their strengths, and share recommendations for different development scenarios—frontend and backend.


Why IaC?

Using IaC comes with some clear benefits:

  • Reproducible setups
    → Easily spin up multiple environments (e.g., dev, staging, prod).

  • Fewer human errors
    → No risk of misclicking in the console.

  • Automation-friendly
    → Since your infra is code, you can seamlessly integrate it into pipelines (e.g., GitHub Actions).


IaC Options on AWS

The three main IaC options in the AWS ecosystem are:

  • CloudFormation
  • AWS SAM (Serverless Application Model)
  • AWS CDK (Cloud Development Kit)

Here’s a quick overview:

CloudFormation

  • AWS’s core IaC service
  • Define resources in JSON or YAML
  • Pros: Covers all AWS services, lots of official templates available
  • Cons: Can get verbose; hard to manage at scale

→ Best for: “I want simple templates” or “I want to learn from AWS’s official examples.”

AWS SAM

  • Built on top of CloudFormation
  • Tailored for serverless apps (Lambda, API Gateway, DynamoDB, etc.)
  • Handy CLI (sam build, sam local invoke, sam deploy)
  • Pros: Minimal config for serverless workloads
  • Cons: Not great for non-serverless services

→ Best for: “I want to quickly build & deploy a serverless app.”

AWS CDK

  • Lets you define infra using programming languages (TypeScript, Python, Java, etc.)
  • Compiles down to CloudFormation under the hood
  • Pros: Use loops, conditionals, and abstractions—perfect for complex infra
  • Cons: Slightly steeper learning curve

→ Best for: “I want to use my favorite language” or “I need to manage large/complex setups.”


Practical Examples

Frontend Example: React on S3 + CloudFront

  • Recommended: CDK or CloudFormation
  • Typical setup: Deploy React static files to S3, distribute via CloudFront

CDK Example (TypeScript):

import * as cdk from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";

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

    const bucket = new s3.Bucket(this, "FrontendBucket", {
      websiteIndexDocument: "index.html",
      publicReadAccess: false,
    });

    new cloudfront.CloudFrontWebDistribution(this, "FrontendCDN", {
      originConfigs: [
        {
          s3OriginSource: { s3BucketSource: bucket },
          behaviors: [{ isDefaultBehavior: true }],
        },
      ],
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Serverless Backend Example: Lambda + API Gateway

  • Recommended: AWS SAM
  • You can write it in CloudFormation, but SAM makes it much easier

SAM Example (YAML):

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.lambda_handler
      Runtime: python3.11
      Events:
        ApiEvent:
          Type: Api
          Properties:
            Path: /hello
            Method: get
Enter fullscreen mode Exit fullscreen mode

Non-Serverless Backend Example: ECS + VPC + RDS

  • Recommended: CDK
  • Great for managing complex infra like ECS + VPC + RDS

CDK Example (ECS Fargate):

import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ec2 from "aws-cdk-lib/aws-ec2";

const vpc = new ec2.Vpc(this, "MyVpc");
const cluster = new ecs.Cluster(this, "MyCluster", { vpc });

new ecs.FargateService(this, "MyService", {
  cluster,
  taskDefinition: new ecs.FargateTaskDefinition(this, "TaskDef"),
});
Enter fullscreen mode Exit fullscreen mode

Summary

  • CloudFormation
    → The fundamental tool for defining AWS infra in YAML/JSON.

  • AWS SAM
    → Optimized for serverless apps, especially Lambda-heavy projects.

  • AWS CDK
    → Flexible, expressive, and powerful for complex or large-scale infra.

Even if you’re used to clicking around in the AWS Console, adopting IaC unlocks big advantages: reproducibility, environment consistency, and automation.

If you’re new to IaC, I recommend starting small—maybe with your frontend setup—then gradually tying it into CI/CD (like GitHub Actions) for full automation.

Top comments (0)