examhub .cc The most efficient path to the most valuable certifications.
In this note ≈ 32 min

IaC with SAM and CloudFormation

6,400 words · ≈ 32 min read

Infrastructure as Code (IaC) on AWS means writing your cloud infrastructure as declarative text that AWS CloudFormation, AWS SAM, or AWS CDK can deploy, update, and tear down repeatedly. For the AWS Certified Developer Associate (DVA-C02) exam, Task Statement 3.1 expects you to read CloudFormation templates fluently, pick the right intrinsic function for a scenario, understand how SAM shorthand macros expand into raw CloudFormation, debug change sets and drift, and reason about multi-account Stack Sets plus Lambda-backed custom resources. This guide walks through every CloudFormation section, every intrinsic function, every resource attribute, and every SAM + CDK workflow that DVA-C02 puts on the table.

What Is CloudFormation and AWS SAM?

AWS CloudFormation is AWS's declarative Infrastructure as Code service. You write a CloudFormation template in YAML or JSON, describe the desired end state of your AWS resources, and CloudFormation provisions, updates, or deletes those resources as a single atomic unit called a stack. AWS SAM (Serverless Application Model) is a CloudFormation extension that ships shorthand resource types for serverless applications — AWS Lambda functions, Amazon API Gateway APIs, Amazon DynamoDB tables, and AWS Step Functions state machines — that expand into raw CloudFormation at deploy time via the Transform: AWS::Serverless-2016-10-31 macro.

The DVA-C02 exam frames Infrastructure as Code around five questions:

  1. What is the anatomy of a CloudFormation template (Resources, Parameters, Outputs, Mappings, Conditions, Rules, Metadata, Transform)?
  2. Which intrinsic function do I call to wire two resources together (Ref, Fn::GetAtt, Fn::Sub, Fn::Join, Fn::ImportValue, Fn::If, Fn::FindInMap, Fn::GetAZs, Fn::Transform)?
  3. How do I control lifecycle behavior on critical resources (DependsOn, DeletionPolicy, UpdateReplacePolicy, CreationPolicy, UpdatePolicy)?
  4. How do I preview and roll out changes safely (change sets, drift detection, rollback, nested stacks, cross-stack exports, Stack Sets)?
  5. How does AWS SAM accelerate Lambda + API Gateway + DynamoDB deployments, and when does AWS CDK become a better fit?

This topic answers all five in the depth DVA-C02 demands. Every section keeps the conversation anchored to Task 3.1's verbs: prepare application artifacts, define Infrastructure as Code, deploy application artifacts to AWS.

AWS CloudFormation is an Infrastructure as Code service that lets you model, provision, and manage AWS and third-party resources using declarative templates written in YAML or JSON. A CloudFormation template describes the desired state of a collection of resources; CloudFormation determines the correct order of API calls, handles rollback on failure, and tracks the resulting stack as a single lifecycle unit. AWS SAM extends CloudFormation with serverless-specific shorthand via the AWS::Serverless-2016-10-31 transform. See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html

CloudFormation Template Anatomy — All Nine Sections

A CloudFormation template is a YAML (or JSON) document with up to nine top-level sections. Only Resources is mandatory. Understanding every section is the foundation of DVA-C02 Task 3.1.

AWSTemplateFormatVersion

AWSTemplateFormatVersion declares the CloudFormation template schema version. The only valid value today is 2010-09-09. CloudFormation is backwards compatible, and omitting this field is legal, but every production CloudFormation template should include it for clarity and future version pinning.

AWSTemplateFormatVersion: "2010-09-09"

Description

Description is a free-form string up to 1024 characters. It surfaces in the AWS Management Console stack list and in aws cloudformation describe-stacks. Good Descriptions in a CloudFormation template save humans in a hurry.

Metadata

Metadata holds structured information about the CloudFormation template that is not consumed by resource provisioning. The most common use is AWS::CloudFormation::Interface to group and order Parameters in the AWS Management Console. SAM also uses Metadata to attach extra attributes to AWS::Serverless::Function resources.

Parameters

Parameters makes a CloudFormation template reusable. You declare inputs (instance type, VPC ID, environment name) and supply them at deploy time via the AWS CLI --parameters flag, CloudFormation console prompts, or CI/CD pipelines. Each parameter has a Type (String, Number, List, CommaDelimitedList, or AWS-specific types like AWS::EC2::VPC::Id), optional Default, AllowedValues, AllowedPattern, MinLength/MaxLength, MinValue/MaxValue, NoEcho (to mask secrets), and Description.

Parameters:
  EnvName:
    Type: String
    AllowedValues: [dev, staging, prod]
    Default: dev
    Description: "Deployment environment"
  DBPassword:
    Type: String
    NoEcho: true
    MinLength: 12

Mappings

Mappings is a static lookup table inside the CloudFormation template. The classic use is picking an AMI ID per Region:

Mappings:
  RegionAMI:
    us-east-1: { AMI: ami-0abcdef1234567890 }
    us-west-2: { AMI: ami-0fedcba0987654321 }

Access via !FindInMap [ RegionAMI, !Ref AWS::Region, AMI ]. Mappings make CloudFormation templates portable across Regions without parameterizing every value.

Conditions

Conditions defines named boolean expressions evaluated at deploy time. You typically compare a Parameter value against a constant and then attach the condition to a resource or output with the Condition: attribute.

Conditions:
  IsProd: !Equals [ !Ref EnvName, prod ]
Resources:
  ProdOnlyBucket:
    Type: AWS::S3::Bucket
    Condition: IsProd

Resources guarded by a false condition are skipped entirely — CloudFormation does not create them, and Ref/GetAtt against them returns AWS::NoValue.

Transform

Transform declares one or more macros that expand the CloudFormation template before resources are created. The most common Transform is AWS::Serverless-2016-10-31 — the AWS SAM transform — which expands SAM shorthand into raw CloudFormation. AWS::Include is another built-in transform for injecting snippets from S3. Custom macros are Lambda functions registered as CloudFormation macros.

Transform: AWS::Serverless-2016-10-31

Resources (mandatory)

Resources is the only mandatory top-level section in a CloudFormation template. Every entry has a Type (for example AWS::S3::Bucket, AWS::Lambda::Function, AWS::DynamoDB::Table) and a Properties block matching that type's schema. Resource logical IDs (the keys under Resources) must be alphanumeric, unique within the template, and are used when other resources Ref or GetAtt against them.

Outputs

Outputs exposes values from your stack for humans, automation, or other stacks. Each output has a Value (often a Ref or Fn::GetAtt) and optionally an Export name — the key that enables cross-stack references via Fn::ImportValue. Outputs are shown in the AWS Management Console and returned by describe-stacks.

Outputs:
  ApiUrl:
    Value: !Sub "https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"
    Export:
      Name: !Sub "${AWS::StackName}-ApiUrl"

Rules

Rules validates parameter combinations at stack creation or update time. A Rule can, for example, require a certain InstanceType only when EnvName is prod. Rules are less common on DVA-C02 but worth recognizing.

A minimal valid CloudFormation template contains just one section: Resources. Every other section (AWSTemplateFormatVersion, Description, Metadata, Parameters, Mappings, Conditions, Transform, Outputs, Rules) is optional. DVA-C02 questions that show a minimal template without AWSTemplateFormatVersion are still valid — do not pick "missing schema version" as the failure cause. The single forced error is a missing Resources section. See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html

Intrinsic Functions — The CloudFormation Wiring Toolkit

Intrinsic functions are how a CloudFormation template references values it does not know at authoring time. Every DVA-C02 candidate must be fluent in the nine canonical intrinsic functions.

Ref

Ref returns the default identifier of a resource or parameter. For AWS::S3::Bucket, Ref returns the bucket name. For AWS::Lambda::Function, Ref returns the function name. For AWS::EC2::Instance, Ref returns the instance ID. For a Parameter, Ref returns the parameter's value. The shorthand form is !Ref ResourceLogicalId.

Fn::GetAtt

Fn::GetAtt retrieves a specific attribute of a resource — typically an ARN, endpoint, or computed value not returned by Ref. Fn::GetAtt takes two arguments: the resource logical ID and the attribute name. Every resource type documents its GetAtt attributes in the CloudFormation User Guide.

MyFunctionArn: !GetAtt MyFunction.Arn
DbEndpoint:   !GetAtt Database.Endpoint.Address

Fn::Sub

Fn::Sub substitutes variables into a string, similar to template literals in JavaScript. It is the most flexible string-building intrinsic function. Fn::Sub automatically resolves ${AWS::Region}, ${AWS::AccountId}, and other pseudo parameters, plus any local Parameter or Resource logical ID.

ApiUrl: !Sub "https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/prod"
LambdaName: !Sub "${AWS::StackName}-handler"

Fn::Join

Fn::Join concatenates a list of strings with a delimiter: !Join [ "-", [ !Ref EnvName, "bucket", !Ref AWS::AccountId ] ]. Fn::Sub is almost always cleaner than Fn::Join, but Fn::Join remains common in older CloudFormation templates and appears on DVA-C02.

Fn::ImportValue

Fn::ImportValue reads an exported output from another stack in the same Region and account. It is the cross-stack reference primitive: one stack Exports, another stack ImportValues. The exporting stack cannot be deleted while an importing stack still references its export — CloudFormation enforces this dependency.

VpcId: !ImportValue NetworkStack-VpcId

Fn::If

Fn::If is a ternary operator keyed on a named condition. It takes three arguments: the condition name, the value to return if true, and the value to return if false. AWS::NoValue is a special value that tells CloudFormation to omit the property entirely.

BucketName: !If [ IsProd, "prod-data", !Ref AWS::NoValue ]

Fn::GetAZs

Fn::GetAZs returns the list of Availability Zones available in a given Region. Pass an empty string to get AZs for the current Region: !GetAZs "". Combine with Fn::Select to pick a specific AZ index.

Fn::FindInMap

Fn::FindInMap looks up a value in the Mappings section by a three-key path: top-level key, second-level key, attribute name. The canonical use is region-to-AMI lookup.

ImageId: !FindInMap [ RegionAMI, !Ref AWS::Region, AMI ]

Fn::Transform

Fn::Transform invokes a macro at a specific location in the CloudFormation template. Unlike the top-level Transform section (which runs once), Fn::Transform can inject processed output inside a Resources block. It is the escape hatch that makes custom macros and AWS::Include usable mid-template.

When building interpolated strings in a CloudFormation template, prefer Fn::Sub (!Sub) over Fn::Join (!Join). !Sub "${MyResource.Arn}" reads exactly like a shell variable; !Join [ "", [ !GetAtt MyResource.Arn ] ] is noisy and error-prone. Fn::Sub also natively resolves pseudo parameters such as ${AWS::Region} and ${AWS::StackName} without any extra ceremony. Reserve Fn::Join for cases where the delimiter genuinely matters (ARN construction with colons, CSV strings). See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html

Pseudo Parameters — Values AWS Injects for You

Pseudo parameters are values CloudFormation pre-populates and resolves at deploy time. You do not declare them; you just reference them like any other parameter. DVA-C02 tests the following pseudo parameters heavily:

  • AWS::Region — the Region where the stack is deployed (for example us-east-1).
  • AWS::AccountId — the 12-digit AWS account ID hosting the stack.
  • AWS::StackName — the name of the stack being deployed, useful for name-prefixing resources.
  • AWS::StackId — the full ARN of the stack.
  • AWS::Partition — the AWS partition (aws, aws-cn, or aws-us-gov), critical for ARN construction in multi-partition deployments.
  • AWS::URLSuffix — the DNS suffix for the partition (amazonaws.com, amazonaws.com.cn).
  • AWS::NoValue — sentinel that tells CloudFormation to omit a property, most often returned from Fn::If branches.
  • AWS::NotificationARNs — the list of SNS topic ARNs associated with the stack.

Hard-coding a Region string like us-east-1 into a CloudFormation template is a classic DVA-C02 anti-pattern. The correct value is always !Ref AWS::Region or ${AWS::Region} inside Fn::Sub.

Resource Attributes — DependsOn, DeletionPolicy, UpdateReplacePolicy, CreationPolicy, UpdatePolicy

Resource attributes sit alongside Type and Properties on any CloudFormation resource and control lifecycle behavior. They are the most commonly missed DVA-C02 test targets.

DependsOn

DependsOn adds an explicit ordering dependency. CloudFormation already infers most dependencies from Ref and Fn::GetAtt, but some relationships (IAM policy propagation, VPC Gateway attachments, cross-service eventual consistency) need a manual hint. DependsOn accepts a single logical ID or a list.

MyFunction:
  Type: AWS::Lambda::Function
  DependsOn: [ LoggingPolicy, NetworkInterfaces ]

DeletionPolicy

DeletionPolicy controls what happens to a resource when the containing stack is deleted, or when the resource itself is removed from the template. Three values:

  • Delete (default) — remove the resource when the stack is deleted.
  • Retain — leave the resource in place; CloudFormation disowns it.
  • Snapshot — take a final snapshot before deletion (supported for RDS DB instances, RDS DB clusters, EBS volumes, ElastiCache clusters, Redshift clusters, and Neptune clusters).

For production CloudFormation templates, DeletionPolicy: Retain on S3 buckets with important data and DeletionPolicy: Snapshot on databases are the go-to defensive defaults.

UpdateReplacePolicy

UpdateReplacePolicy controls what happens to the old resource when a stack update triggers replacement — that is, when a property change forces CloudFormation to delete the current resource and create a new one. The same three values apply: Delete, Retain, Snapshot. DeletionPolicy governs stack deletion; UpdateReplacePolicy governs replacement during updates. Both are typically set together on stateful resources.

Database:
  Type: AWS::RDS::DBInstance
  DeletionPolicy: Snapshot
  UpdateReplacePolicy: Snapshot
  Properties: { ... }

CreationPolicy

CreationPolicy forces CloudFormation to wait for an explicit success signal before marking a resource CREATE_COMPLETE. The typical use is waiting for EC2 bootstrap scripts (cfn-init plus cfn-signal) or Auto Scaling group instances to finish boot. CreationPolicy takes ResourceSignal.Count and ResourceSignal.Timeout (ISO 8601 duration).

WebServer:
  Type: AWS::EC2::Instance
  CreationPolicy:
    ResourceSignal:
      Count: 1
      Timeout: PT15M

UpdatePolicy

UpdatePolicy controls how CloudFormation updates certain resources (Auto Scaling groups, Lambda aliases, ElastiCache replication groups). For AWS::AutoScaling::AutoScalingGroup, two sub-policies dominate DVA-C02:

  • AutoScalingRollingUpdate — roll instances in batches while keeping minimum in-service count; parameters include MinInstancesInService, MaxBatchSize, PauseTime, WaitOnResourceSignals.
  • AutoScalingReplacingUpdate — create an entirely new Auto Scaling group, cut over, then delete the old group. Safer rollback but doubles resource count during the update.
AppASG:
  Type: AWS::AutoScaling::AutoScalingGroup
  UpdatePolicy:
    AutoScalingRollingUpdate:
      MinInstancesInService: 2
      MaxBatchSize: 1
      PauseTime: PT5M
      WaitOnResourceSignals: true

DVA-C02 commonly tests the distinction: DeletionPolicy fires when the stack itself is deleted (or the resource is removed from the template); UpdateReplacePolicy fires when a stack update triggers a resource replacement. Setting only DeletionPolicy: Retain on an RDS instance still lets an update silently replace and delete the original if you change a forces-replacement property. For genuinely irreplaceable production state, set both: DeletionPolicy: Snapshot AND UpdateReplacePolicy: Snapshot. See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatereplacepolicy.html

Change Sets — Preview Before You Commit

A CloudFormation change set is a preview of what CloudFormation will do when you next update the stack. You generate a change set with aws cloudformation create-change-set --stack-name ... --template-body file://template.yaml --change-set-name preview1. CloudFormation computes the diff between current stack state and the new template, producing a list of Add, Modify, or Remove actions. For each Modify it classifies the replacement behavior as True (resource will be replaced), False (in-place update), or Conditional (depends on other properties). You then review the change set and either aws cloudformation execute-change-set or delete it.

Change sets are the DVA-C02-favored safety mechanism for production CloudFormation updates. They expose hidden replacements (like the classic RDS DBInstanceIdentifier change) before you click execute. SAM deploys use change sets under the hood by default — sam deploy runs create-change-set then execute-change-set.

Drift Detection — Catching Out-of-Band Changes

Drift detection compares a stack's expected state (what CloudFormation believes based on the last deploy) against the actual current state in AWS. You trigger drift detection via aws cloudformation detect-stack-drift or the AWS Management Console. Each resource is classified as IN_SYNC, MODIFIED, DELETED, or NOT_CHECKED.

Drift happens when operators bypass CloudFormation — editing a Security Group in the AWS Management Console, deleting an S3 bucket with the AWS CLI, or tweaking an IAM policy outside the template. The DVA-C02 exam wants you to know:

  • Drift detection is read-only. It does not fix drift.
  • Not all resource types are drift-supported. Unsupported types report NOT_CHECKED.
  • Remediating drift typically means either updating the template to match actual state, or re-deploying the stack to overwrite the out-of-band changes.

Nested Stacks vs Cross-Stack References

CloudFormation gives you two modularization patterns: nested stacks and cross-stack references. Both appear on DVA-C02.

Nested Stacks

A nested stack is a CloudFormation stack created as a resource inside another stack using AWS::CloudFormation::Stack. The parent stack's Properties.TemplateURL points to an S3 URL holding the child template. Nested stacks are owned by the parent — deleting the parent cascades to all nested children. They are ideal for packaging reusable components (a standard VPC module, a standard logging module) that you instantiate from many parent stacks.

NetworkStack:
  Type: AWS::CloudFormation::Stack
  Properties:
    TemplateURL: https://s3.amazonaws.com/my-bucket/network.yaml
    Parameters:
      VpcCidr: 10.0.0.0/16

Cross-Stack References with Export + Fn::ImportValue

Cross-stack references decouple stacks. Stack A Exports an output; Stack B Fn::ImportValues it. The two stacks have independent lifecycles — but once imported, the exporting stack cannot be deleted or modified in a way that removes the export while the importing stack still consumes it. Export names must be unique per Region per account.

# Stack A (network)
Outputs:
  VpcId:
    Value: !Ref Vpc
    Export: { Name: NetworkStack-VpcId }

# Stack B (app)
Resources:
  AppSG:
    Properties:
      VpcId: !ImportValue NetworkStack-VpcId

Nested Stacks vs Cross-Stack References — Decision Matrix

Axis Nested Stacks Cross-Stack References
Coupling Tight (parent owns children) Loose (independent stacks)
Lifecycle Deleted together with parent Independent; delete blocked while importer exists
Passing data Via Parameters to nested stack Via Export/ImportValue
Best for Reusable module instantiated per parent Shared infrastructure consumed by many apps
DVA-C02 signal "Reusable template fragment" "Separate stacks sharing a VPC ID"

AWS SAM — Serverless Shorthand for CloudFormation

AWS SAM (Serverless Application Model) is a CloudFormation Transform plus a CLI. The Transform: AWS::Serverless-2016-10-31 declaration at the top of a SAM template tells CloudFormation to expand SAM resource types into full CloudFormation before deployment.

SAM Resource Types

The SAM-specific resource types DVA-C02 expects you to know:

  • AWS::Serverless::Function — expands into AWS::Lambda::Function, AWS::IAM::Role, AWS::Lambda::Permission, CloudWatch Logs group, and event-source mappings. Properties like Events auto-generate API Gateway routes, EventBridge rules, SQS triggers, and S3 notifications.
  • AWS::Serverless::Api — expands into AWS::ApiGateway::RestApi, AWS::ApiGateway::Stage, AWS::ApiGateway::Deployment. SAM can also generate an HTTP API via AWS::Serverless::HttpApi.
  • AWS::Serverless::StateMachine — expands into AWS::StepFunctions::StateMachine plus its IAM role.
  • AWS::Serverless::SimpleTable — expands into AWS::DynamoDB::Table with a simple primary key schema.
  • AWS::Serverless::LayerVersion — expands into AWS::Lambda::LayerVersion.
  • AWS::Serverless::Application — nested SAM applications pulled from the Serverless Application Repository or S3.

SAM Globals

Globals is a SAM-specific section where you set defaults applied across every function or API in the template. Common globals include Function.Runtime, Function.Timeout, Function.Environment.Variables, Function.Tracing, and Api.Cors. Globals dramatically shorten templates with many similar Lambda functions.

Globals:
  Function:
    Runtime: python3.12
    Timeout: 30
    Tracing: Active
    Environment:
      Variables:
        TABLE_NAME: !Ref DataTable

SAM CLI — sam build, sam deploy, sam local invoke, sam local start-api

The SAM CLI is the local companion to SAM templates. The commands DVA-C02 expects you to recognize:

  • sam init — scaffolds a new SAM project from a template (zip or container, runtime, hello-world starter).
  • sam build — compiles source code and dependencies into a deployment-ready artifact under .aws-sam/build/. Uses the runtime's build tooling (pip, npm, mvn, go mod).
  • sam deploy — uploads artifacts to S3, generates a CloudFormation change set, and optionally executes it. --guided walks you through parameters interactively.
  • sam local invoke — runs a specific Lambda function locally in a Docker container that mirrors the AWS Lambda runtime. Takes an event JSON payload via --event event.json. Perfect for unit-test-style single-function debugging.
  • sam local start-api — spins up a local HTTP server emulating Amazon API Gateway, routing requests to your Lambda functions in local Docker containers. Test the full API surface without deploying.
  • sam local start-lambda — starts a local Lambda endpoint that mirrors the AWS Lambda Invoke API, so SDK clients pointed at http://127.0.0.1:3001 will hit local functions.
  • sam logs — tails CloudWatch Logs for a deployed function; --tail streams live.
  • sam sync — rapid inner-loop deploys that skip the full CloudFormation change set for code-only changes.
  • sam validate — lints the SAM template.
  • sam delete — deletes the CloudFormation stack created by sam deploy.

SAM Pipelines

sam pipeline init scaffolds a CI/CD pipeline (CodePipeline, GitHub Actions, GitLab CI, Jenkins, or Bitbucket Pipelines) that deploys a SAM application across multiple stages and AWS accounts. It generates IAM roles with least-privilege permissions for each stage and a pipeline configuration file. SAM Pipelines is the quickest path from "I have a SAM template" to "I have multi-environment CI/CD" for DVA-C02 scenarios asking "how do I automate serverless deployments?"

The two SAM local commands most frequently tested on DVA-C02 are:

  1. sam local invoke — run a single Lambda locally in Docker with an event JSON. Use when testing one function with crafted input.
  2. sam local start-api — start a local API Gateway + Lambda Docker environment. Use when testing the full HTTP surface end to end.

If a question says "test one Lambda with a specific event payload," the answer is sam local invoke. If a question says "test the REST API locally with curl or Postman," the answer is sam local start-api. See: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html

AWS CDK — Infrastructure in Real Programming Languages

AWS CDK (Cloud Development Kit) v2 lets you define CloudFormation stacks in TypeScript, JavaScript, Python, Java, C#, and Go. CDK code synths (synthesizes) into a CloudFormation template and uses CloudFormation as its deployment engine. CDK's value proposition over raw CloudFormation: loops, conditionals, classes, unit testing, and a rich library of pre-built constructs with sensible defaults.

Construct Levels — L1, L2, L3

CDK organizes building blocks into three levels:

  • L1 constructs (Cfn classes)* — one-to-one mappings of CloudFormation resource types. CfnBucket maps to AWS::S3::Bucket with exactly the same properties. Use when you need the escape hatch to raw CloudFormation.
  • L2 constructs — curated, opinionated wrappers with sensible defaults and helper methods. s3.Bucket adds grantRead, grantWrite, automatic encryption, and versioning flags — all producing the right CloudFormation under the hood. L2 is the idiomatic layer for most CDK code.
  • L3 constructs (patterns) — multi-resource compositions. aws_ecs_patterns.ApplicationLoadBalancedFargateService provisions an ECS Fargate service plus an Application Load Balancer plus autoscaling plus CloudWatch alarms in one call. L3 constructs dramatically reduce template size for common architectures.

CDK CLI Commands

  • cdk init — bootstrap a new CDK project.
  • cdk synth — synthesize the CloudFormation template from CDK code. Output lives under cdk.out/.
  • cdk diff — compare the synthesized template against the currently deployed stack; reports [+], [-], [~] changes.
  • cdk deploy — synth plus CloudFormation deploy, creating or updating the stack.
  • cdk destroy — tear down the stack.
  • cdk bootstrap — create the staging resources (S3 bucket, IAM role) CDK needs in a target account and Region before first deploy.

CDK Context and Aspects

  • Context — a CDK mechanism for passing runtime configuration via cdk.json or -c key=value on the CLI. Context values are cached after first lookup for reproducibility. Common use: environment-specific feature flags.
  • Aspects — cross-cutting visitors that walk the construct tree and apply changes uniformly. Typical uses: enforce tagging policies, require encryption on every S3 bucket, add removal policies to every stateful resource. Aspects are CDK's answer to "apply this rule to every resource in the app."

SAM vs CDK vs Raw CloudFormation

Dimension Raw CloudFormation AWS SAM AWS CDK
Language YAML / JSON YAML / JSON with Transform TypeScript, Python, Java, C#, Go
Best for Any AWS resource, large orgs with YAML review culture Lambda + API Gateway + DynamoDB serverless stacks Multi-service apps with programmatic composition
Loops and conditionals Mappings + Conditions only Inherits CloudFormation + Globals Native language
Local test No native sam local invoke + sam local start-api Unit tests + cdk synth
Output Direct CloudFormation Expanded CloudFormation Synthesized CloudFormation
DVA-C02 emphasis Template anatomy + intrinsic functions Transform + SAM CLI + serverless resources Construct levels + cdk commands

Parameter Overrides, Change Sets, and Deploy-Time Controls

aws cloudformation deploy --parameter-overrides and sam deploy --parameter-overrides let you pass Parameter values without editing the CloudFormation template. Combined with --capabilities CAPABILITY_IAM or CAPABILITY_NAMED_IAM (required when the template creates or names IAM resources) and --no-execute-changeset (generate but do not execute), parameter overrides are the glue between a single reusable template and multiple environments in a CI/CD pipeline.

Stack Sets — Multi-Account, Multi-Region Deployment

AWS CloudFormation StackSets lets a single administrator account deploy the same CloudFormation template across many target accounts and Regions in one operation. Two permission models matter on DVA-C02:

  • Self-managed permissions — you manually create trust IAM roles (AWSCloudFormationStackSetAdministrationRole in the admin account, AWSCloudFormationStackSetExecutionRole in each target account). Gives the most control; required when target accounts are not part of an AWS Organization.
  • Service-managed permissions — StackSets automatically manages IAM trust across an AWS Organization. Enables auto-deployment to new accounts as they join an OU. Simplest for organizations already on AWS Organizations.

StackSet operation parameters like MaxConcurrentCount, FailureToleranceCount, and RegionConcurrencyType control blast radius during rollouts. Use StackSets when a DVA-C02 scenario says "deploy the same template to many accounts" or "roll out a baseline stack across the organization."

cfn-init and cfn-signal — EC2 Bootstrap from Templates

For EC2-based workloads, CloudFormation ships helper scripts pre-installed on Amazon Linux AMIs:

  • cfn-init — reads the AWS::CloudFormation::Init metadata on an EC2 instance resource and applies it: install packages, create files, start services, run commands. This is CloudFormation's answer to configuration management inside the instance boot.
  • cfn-signal — sends a signal to CloudFormation saying "I am ready" (or "I failed"). Paired with CreationPolicy.ResourceSignal, it makes CloudFormation wait for the instance to finish bootstrap before marking the resource CREATE_COMPLETE.
  • cfn-get-metadata — fetch metadata at runtime.
  • cfn-hup — a daemon that re-runs cfn-init when the stack's metadata changes, enabling in-place reconfiguration.

A canonical EC2 bootstrap in a CloudFormation template:

WebServer:
  Type: AWS::EC2::Instance
  CreationPolicy:
    ResourceSignal: { Count: 1, Timeout: PT10M }
  Metadata:
    AWS::CloudFormation::Init:
      config:
        packages: { yum: { httpd: [] } }
        services: { sysvinit: { httpd: { enabled: true, ensureRunning: true } } }
  Properties:
    UserData:
      Fn::Base64: !Sub |
        #!/bin/bash -xe
        yum update -y aws-cfn-bootstrap
        /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServer --region ${AWS::Region}
        /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServer --region ${AWS::Region}

Custom Resources — Extending CloudFormation with Lambda

Custom resources let you execute arbitrary logic during CloudFormation stack operations. You declare AWS::CloudFormation::CustomResource or the shorter Custom::<Name> with a ServiceToken pointing to a Lambda function (or SNS topic). CloudFormation invokes the Lambda with a RequestType of Create, Update, or Delete and waits for the function to send a signed response to a pre-signed S3 URL.

Use cases tested on DVA-C02:

  • Generating random values (random S3 bucket suffixes) at deploy time.
  • Calling third-party APIs (create an Auth0 tenant during stack deploy).
  • Configuring AWS services that have no native CloudFormation resource type yet.
  • Post-deploy initialization (seed a DynamoDB table with default rows).

Custom resources must always respond to CloudFormation within the timeout or the stack hangs in CREATE_IN_PROGRESS until it eventually fails. Best practice: the Lambda handler must wrap all logic in try/except and always send a response — SUCCESS or FAILED — even when logic fails.

DVA-C02 commonly tests the failure mode where a custom resource Lambda throws an unhandled exception and never sends a response to the pre-signed S3 URL. CloudFormation has no way to know the Lambda failed — it waits up to 1 hour before giving up, trapping the stack in CREATE_IN_PROGRESS or DELETE_IN_PROGRESS. The fix: always wrap custom resource handlers in try/except/finally and always POST to event.ResponseURL with { "Status": "SUCCESS" | "FAILED", ...}. Many SDK helpers (cfnresponse for Python, aws-cdk-lib/custom-resources for CDK) implement this pattern correctly. See: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html

CloudFormation Rollback and Stack Failure Behaviors

When a CloudFormation stack operation fails, CloudFormation automatically rolls back by default. Key behaviors DVA-C02 tests:

  • CREATE_FAILED → ROLLBACK_IN_PROGRESS → ROLLBACK_COMPLETE — failed create rolls back; the stack ends in ROLLBACK_COMPLETE. A stack in ROLLBACK_COMPLETE cannot be updated — you must delete and recreate it.
  • UPDATE_FAILED → UPDATE_ROLLBACK_IN_PROGRESS → UPDATE_ROLLBACK_COMPLETE — failed update rolls back to the last-known-good state.
  • DisableRollback — pass --disable-rollback on create-stack or update-stack to skip automatic rollback. Useful for debugging: resources stay in whatever state they reached.
  • ContinueUpdateRollback — resume a rollback that got stuck because a resource could not be rolled back (for example, an S3 bucket was manually deleted after partial success).

Common DVA-C02 Exam Traps

Trap 1: Ref vs Fn::GetAtt

Ref returns the default identifier (bucket name, function name, instance ID). Fn::GetAtt returns a specific attribute (ARN, endpoint, hosted zone ID). When a question asks for "the ARN of this Lambda," the answer is !GetAtt MyFunction.Arn, not !Ref MyFunction.

Trap 2: Fn::ImportValue vs Nested Stack Parameters

Fn::ImportValue crosses stack boundaries via Export. Nested stacks pass data via Parameters on AWS::CloudFormation::Stack. If the question shows two independent stacks sharing a VPC ID, the answer is Export + Fn::ImportValue. If the question shows one parent template instantiating a reusable child, the answer is nested stack parameters.

Trap 3: DeletionPolicy Does Not Protect Against Updates

Setting DeletionPolicy: Retain protects against stack deletion, not against in-place replacement during updates. For that, add UpdateReplacePolicy: Retain.

Trap 4: SAM Transform Must Be at the Top

A SAM template without Transform: AWS::Serverless-2016-10-31 is just a broken CloudFormation template. CloudFormation will reject AWS::Serverless::Function as an unknown resource type. The Transform line is mandatory for SAM.

Trap 5: CDK Requires Bootstrap Before First Deploy

Running cdk deploy in a new account/Region without first running cdk bootstrap fails with a missing CDKToolkit stack error. Bootstrap creates the S3 bucket and IAM roles CDK needs to stage assets.

Trap 6: sam local invoke Requires Docker

sam local invoke and sam local start-api spin up Lambda runtime emulators in Docker containers. Without Docker installed and running, both commands fail. Linux, macOS, and Windows all need the Docker daemon.

Trap 7: Change Sets Do Not Apply Themselves

Creating a change set is preview-only. Until you call execute-change-set, nothing deploys. Forgetting the execute step is a common DVA-C02 distractor.

Trap 8: StackSets Self-Managed vs Service-Managed Permissions

Service-managed permissions require AWS Organizations. Self-managed permissions work across arbitrary accounts but require manual IAM role setup in each target. Pick service-managed when the scenario says "all accounts in the organization"; pick self-managed when the scenario says "these specific accounts" or explicitly rules out Organizations.

Trap 9: Drift Detection Is Read-Only

Drift detection reports differences but does not fix them. Remediating drift means re-deploying the stack to overwrite the out-of-band changes or updating the template to reflect actual state.

Trap 10: Custom Resource Silent Hang

Custom resource Lambdas that fail silently trap stacks in IN_PROGRESS for up to an hour. Always send a response in a finally block.

Key Numbers and Must-Memorize Facts

DVA-C02 asks exact numbers less often than CLF-C02, but a few CloudFormation and SAM limits surface in scenarios:

  • CloudFormation template size: 1 MB for direct upload, 1 MB for S3-hosted templates (unchanged since launch).
  • Resources per stack: 500 (soft limit; adjustable).
  • Parameters per template: 200.
  • Outputs per template: 200.
  • Mappings per template: 200.
  • Stack Set operations: default 10 concurrent accounts, configurable via MaxConcurrentCount.
  • Custom resource Lambda timeout response window: up to 1 hour before CloudFormation times out.
  • CreationPolicy timeout: ISO 8601 duration, typically PT15M for EC2 bootstrap, configurable per resource.
  • SAM Transform version: AWS::Serverless-2016-10-31 (yes, the date is the version — do not change it).
  • CDK v2 supported languages: TypeScript, JavaScript, Python, Java, C#, Go.
  • CDK bootstrap stack name: CDKToolkit.
  • CloudFormation helper scripts: cfn-init, cfn-signal, cfn-get-metadata, cfn-hup.

Infrastructure as Code Decision Tree for DVA-C02

When a DVA-C02 question asks "which tool?" walk this decision tree:

  1. Is the workload purely serverless (Lambda + API Gateway + DynamoDB + Step Functions)? → AWS SAM.
  2. Is the team comfortable writing TypeScript, Python, Java, C#, or Go and wants loops, unit tests, and patterns? → AWS CDK.
  3. Is the team operating at enterprise scale with a YAML-centric review process and wants raw control? → Raw AWS CloudFormation.
  4. Need to deploy the same stack across many accounts or Regions? → CloudFormation StackSets on top of any of the above.
  5. Need to inject deploy-time logic CloudFormation cannot express natively? → Custom Resource backed by Lambda.
  6. Need fast local iteration on a Lambda function? → sam local invoke or sam local start-api.
  7. Need to preview the blast radius of a stack update? → Change set via create-change-set.
  8. Suspect someone clicked past your CloudFormation template? → Drift detection.

FAQ — IaC with SAM and CloudFormation

Q1: What is the difference between AWS CloudFormation, AWS SAM, and AWS CDK? A: AWS CloudFormation is the underlying declarative Infrastructure as Code engine using YAML or JSON. AWS SAM is a CloudFormation Transform plus CLI that shortens serverless templates — AWS::Serverless::Function expands into the full Lambda + IAM Role + Log Group + event sources during deploy. AWS CDK lets you write CloudFormation stacks in TypeScript, Python, Java, C#, or Go; it synthesizes CloudFormation templates and deploys them. All three end up calling CloudFormation — they differ in authoring ergonomics.

Q2: When should I use Fn::ImportValue vs nested stack Parameters? A: Use Fn::ImportValue when two stacks have independent lifecycles and share a long-lived resource ID (like a VPC ID or shared KMS key ARN). Use nested stack Parameters when one parent template owns and instantiates reusable child templates — the children exist only as part of the parent stack and die with it. ImportValue enforces a strong coupling: the exporting stack cannot delete the export while any stack imports it.

Q3: What does DeletionPolicy: Retain do and how is it different from UpdateReplacePolicy: Retain? A: DeletionPolicy: Retain tells CloudFormation to leave the resource in place when the stack itself is deleted (or when the resource is removed from the template). UpdateReplacePolicy: Retain tells CloudFormation to leave the old resource in place when a stack update triggers replacement (for example, renaming an RDS instance). Both are needed together for irreplaceable production state. Supported values for both: Delete, Retain, Snapshot (the last only for stateful resources like RDS, EBS, ElastiCache, Redshift, Neptune).

Q4: When do I use sam local invoke vs sam local start-api? A: Use sam local invoke to test a single Lambda function with a specific event JSON — perfect for unit-test-style runs where you craft inputs. Use sam local start-api to launch a local HTTP server that emulates API Gateway and routes incoming requests to your Lambdas — perfect for end-to-end REST API testing with curl, Postman, or a browser. Both require Docker.

Q5: What are CDK L1, L2, and L3 constructs and when do I pick each level? A: L1 constructs (Cfn* classes) are one-to-one mappings of raw CloudFormation resource types — use them as an escape hatch when an L2 construct does not expose a property. L2 constructs are curated wrappers with sensible defaults, helper methods (grantRead, grantWrite), and sane security defaults — the idiomatic layer for most CDK code. L3 constructs (patterns) are multi-resource blueprints like ApplicationLoadBalancedFargateService — use them when the pattern matches your architecture and you want minimal code.

Q6: How do change sets differ from direct stack updates? A: A change set is a preview. aws cloudformation create-change-set computes the diff between current stack state and the new template, lists every Add, Modify, or Remove action, and classifies replacements. Nothing changes in your account until you run execute-change-set. Direct update-stack applies the changes immediately without a preview. For production, change sets are the DVA-C02 recommended safety net — they expose hidden replacements (like RDS identifier renames) before execution. sam deploy uses change sets under the hood by default.

Q7: What is drift detection and can it fix drift? A: Drift detection compares a CloudFormation stack's expected state (from the last deploy) against actual state in AWS. It classifies each resource as IN_SYNC, MODIFIED, DELETED, or NOT_CHECKED. Drift detection is read-only — it reports but does not fix drift. Remediation is manual: either update the template to match actual state, or re-deploy the stack to overwrite out-of-band changes. Not all resource types support drift detection; unsupported types report NOT_CHECKED.

Q8: When are Stack Sets with service-managed permissions the right choice? A: Choose service-managed permissions when your target accounts are part of an AWS Organization and you want StackSets to handle IAM trust automatically, including auto-deploy to new accounts that join a specified OU. Choose self-managed permissions when targets are not in an Organization, or when you need fine-grained manual control over the administration and execution IAM roles. DVA-C02 scenarios mentioning "AWS Organizations" or "all accounts in an OU" usually point to service-managed.

Q9: Why would a custom resource Lambda trap a stack in CREATE_IN_PROGRESS? A: Custom resources require the Lambda to POST a response (SUCCESS or FAILED) to a pre-signed S3 URL in the event. If the Lambda throws an unhandled exception and exits without responding, CloudFormation waits up to 1 hour before giving up — trapping the stack in CREATE_IN_PROGRESS or DELETE_IN_PROGRESS. The fix: wrap all custom resource handler logic in try/except/finally and always send a response, even on failure. Libraries like cfnresponse (Python) and aws-cdk-lib/custom-resources implement this pattern correctly.

Q10: What do cfn-init and cfn-signal do on an EC2 instance? A: cfn-init reads the AWS::CloudFormation::Init metadata on an EC2 resource and applies it — install packages, create files, start services, run commands. cfn-signal sends a success or failure signal to CloudFormation from inside the instance. Paired with CreationPolicy.ResourceSignal, CloudFormation waits for cfn-signal before marking the resource CREATE_COMPLETE. This pattern is how you guarantee the stack does not advance until an EC2 instance finishes bootstrap — the EC2-native answer for deploy-time configuration that CloudFormation itself cannot perform.

Further Reading — Official AWS Documentation

Mastering Infrastructure as Code is the fastest way to raise your DVA-C02 Domain 3 score. Internalize the nine CloudFormation template sections, the nine intrinsic functions, the three pseudo parameters you reuse everywhere (AWS::Region, AWS::AccountId, AWS::StackName), the five resource attributes (DependsOn, DeletionPolicy, UpdateReplacePolicy, CreationPolicy, UpdatePolicy), the change set and drift detection workflows, the SAM Transform plus the sam local invoke / sam local start-api pair, and the CDK L1/L2/L3 construct hierarchy. Every DVA-C02 Task 3.1 question reduces to choosing the right CloudFormation primitive, the right SAM shorthand, or the right CDK construct from these lists.

Official sources