AWS CloudFormation, SAM & CDK

Infrastructure as Code (IaC) means describing your AWS resources in a file instead of clicking through the console — so environments become versioned, repeatable, and reviewable like any other code. CloudFormation is the underlying provisioning engine for all of AWS IaC; SAM and CDK are two different authoring layers on top of it. Everything a developer does with SAM or CDK eventually becomes a CloudFormation template deployed as a CloudFormation stack — understanding that relationship is the single most important idea in this module.

Deployment — primary domain Development — SAM/CDK CLI tooling Troubleshooting — rollback & drift
500
Max resources per stack
5
Max nested stack depth
3
CDK construct levels (L1–L3)
Free
CFN/SAM/CDK tooling itself — you pay only for provisioned resources

The One Idea That Unlocks This Whole Topic

Three Tools, One Engine

Core Components (CloudFormation Template Anatomy)

The Template Sections
⚠️ The Recurring Exam Theme

Nearly every IaC question on DVA-C02 tests one of three things: (1) can you pick the right tool for a described team/workload (raw CloudFormation vs SAM vs CDK), (2) do you understand a specific safety mechanism — change sets, drift detection, stack policies, DeletionPolicy/UpdateReplacePolicy, rollback — well enough to apply it to a scenario, or (3) can you trace a SAM/CDK CLI command to what it actually does under the hood (build vs package vs deploy; synth vs deploy).

Exam Domain Mapping (DVA-C02)

DomainWhere IaC Shows Up
Domain 1 — Development with AWS Services (32%)Using the SAM CLI and CDK CLI as development tooling; local testing (sam local invoke); AWS SDK/CLI usage that these tools wrap
Domain 2 — Security (26%)Least-privilege CloudFormation service roles; NoEcho parameters vs Secrets Manager/SSM dynamic references; IAM permissions for stack operations
Domain 3 — Deployment (24%)The centerpiece — templates, stacks, change sets, nested stacks, SAM deploy, CDK deploy, deployment configuration across environments
Domain 4 — Troubleshooting and Optimization (18%)Stack rollback behavior, drift detection, stuck rollback recovery (ContinueUpdateRollback), diagnosing failed deployments from stack events

IaC content is spread across all four domains rather than parked in one — that breadth is exactly why it's worth mastering deeply rather than skimming.

How It Actually Works — From Code to Live Stack

Author

Choose your abstraction: raw CloudFormation YAML/JSON, a SAM template (CloudFormation + Transform), or a CDK app written in a general-purpose language

Synthesize

cdk synth runs your CDK app and emits a plain CloudFormation template into cdk.out. SAM's Transform is expanded server-side by CloudFormation itself at deploy time. A raw template needs no synth step — it already is the CloudFormation template.

Build & Package

sam build compiles/packages function code (in a Docker container matching the Lambda runtime, for compiled dependencies). Local assets — Lambda zips, Docker images — are then uploaded to a staging S3 bucket / ECR repository, and the template is rewritten with the resulting artifact locations.

Deploy

sam deploy / cdk deploy / aws cloudformation deploy all ultimately call the same CloudFormation CreateStack/UpdateStack API (via a change set under the hood) — CloudFormation is the single control plane underneath all three tools

CloudFormation Engine

Resolves intrinsic functions, computes a change set (add/modify/remove, in-place vs replacement), and provisions resources in dependency order

Stack

The live, stateful representation of your resources — supports further updates, drift detection, rollback on failure, and deletion as a single unit

Change sets preview updates Drift detection audits reality DeletionPolicy protects data Stack events show progress/failure

Final Summary

Must Memorize
  • CloudFormation is the engine under both SAM and CDK — SAM/CDK never provision resources on their own
  • cdk synth = produce template only, deploys nothing; cdk deploy = synth + deploy
  • Transform: AWS::Serverless-2016-10-31 is what makes a template "SAM"
  • Change sets preview changes; drift detection audits changes already made out-of-band
  • DeletionPolicy vs UpdateReplacePolicy — one is for delete/removal, one is specifically for replacement during an update
Must Understand
  • When to choose raw CloudFormation vs SAM vs CDK for a described team/workload
  • CDK construct levels (L1 raw / L2 curated / L3 patterns) and what each buys you
  • The SAM CLI local-testing loop (sam local invoke, sam local start-api) and why it matters for developer productivity
  • Nested stacks (tight composition) vs cross-stack exports (loose coupling) vs StackSets (multi-account/region)
Can De-prioritize
  • Exact console UI click-paths
  • Memorizing every intrinsic function's full syntax — know what each is for
  • CDK Pipelines internals beyond knowing it exists for self-mutating CI/CD

Exam appearance probability: HIGH

Components — Deep Dive

The settings, functions, and CLI verbs that show up repeatedly inside scenario questions.

2.1 Parameters, Mappings & Conditions Foundational
ParametersRuntime inputs — support types, AllowedValues/AllowedPattern constraints, Default, and NoEcho (masks console display only — not encryption)
AWS-specific parameter typesAWS::EC2::KeyPair::KeyName, AWS::SSM::Parameter::Value<String> — validated against real AWS values, and the SSM type resolves a Parameter Store value at deploy time
MappingsStatic lookup tables — classic use: Region → AMI ID, read via Fn::FindInMap
ConditionsBoolean logic (Fn::Equals/Fn::And/Fn::Or/Fn::Not) attached to a resource's Condition attribute to decide whether it's created at all — e.g. only create a NAT Gateway when an EnvType parameter equals prod
2.2 Intrinsic Functions High exam relevance
FunctionWhat it's for
RefParameter → returns its input value. Resource → returns that resource's "default" identifier (varies by type, e.g. bucket name for S3, instance ID for EC2)
Fn::GetAttReturns a specific attribute of a resource beyond its default Ref — e.g. !GetAtt Bucket.Arn, !GetAtt MyFunction.Arn
Fn::SubString substitution using ${Placeholder} syntax inline — far more readable than nested Fn::Join
Fn::Join / Fn::Split / Fn::SelectBuild a delimited string / split a string into a list / pick one element from a list
Fn::FindInMapLooks up a value from a Mappings table
Fn::If / Fn::Equals / Fn::And / Fn::Or / Fn::NotConditional logic, usually paired with the Conditions section
Fn::ImportValueReads a value another stack Exported in its Outputs — the mechanism behind cross-stack references
Fn::GetAZs / Fn::CidrReturn Availability Zones for a Region / carve CIDR blocks from a supplied range — common in networking templates
Fn::Base64Base64-encodes a string — routinely used for EC2 UserData
⚠️ Ref vs GetAtt trap

"I need the ARN of this S3 bucket" is never answered with plain Ref (that returns the bucket name) — it needs Fn::GetAtt Bucket.Arn. The exam relies on you knowing Ref's return value differs per resource type.

2.3 Change Sets High-trap
PurposePreview exactly what a stack update will do before it happens
ShowsAdd / Modify / Remove per resource, and for Modify: whether it's an in-place update, brief interruption, or full Replacement
API flowCreateChangeSetDescribeChangeSet (review) → ExecuteChangeSet (commit) — or discard it, nothing has changed yet
2.4 Drift Detection Medium-high
PurposeDetect when a resource's live configuration no longer matches what the template defines
StatesIN_SYNC, MODIFIED, DELETED, NOT_CHECKED
2.5 Nested Stacks, Cross-Stack References & StackSets High exam relevance
Nested stackAWS::CloudFormation::Stack resource — a child template embedded inside a parent, no independent lifecycle, used for reusable building blocks (e.g. a standard VPC pattern)
Cross-stack referenceOne stack Exports an Output value; another stack reads it with Fn::ImportValue — for loosely-coupled, independently-lifecycled stacks sharing a handful of values
StackSetsDeploys the same stack across many accounts and Regions from one administrator account, with per-target parameter overrides — a different scaling axis entirely from nested stacks
2.6 Stack Updates, Rollback & Protection Mechanisms High-trap
Update behaviorPer-property: No interruption / Some interruption (brief downtime) / Replacement (new resource created, old one deleted, logical ID unchanged but physical ID changes)
DeletionPolicyDelete (default) / Retain / Snapshot — controls the resource when it's removed from the template or the whole stack is deleted
UpdateReplacePolicySame options, but specifically for the old resource when an update forces a Replacement — defaults to Delete unless set, a classic trap for RDS/EBS
Default rollbackOn CREATE_FAILED/UPDATE_FAILED, CloudFormation automatically rolls back to the last known-good state
Rollback triggersCloudWatch Alarms attached to a deployment that also force a rollback if metrics breach thresholds during the monitoring window
Stuck rollbackContinueUpdateRollback — skips resources that can't roll back cleanly so the stack can reach a stable state again
Stack PolicyJSON policy on the stack restricting which update actions (e.g. Replace/Delete) are allowed on specific protected resources — applies to updates only, not stack deletion
Termination ProtectionPrevents the stack itself from being deleted (console/CLI/API) until explicitly disabled
2.7 AWS SAM — Templates & CLI High exam relevance
ActivationTransform: AWS::Serverless-2016-10-31 at the top of a CloudFormation template
Shorthand resourcesAWS::Serverless::Function, AWS::Serverless::Api, AWS::Serverless::HttpApi, AWS::Serverless::SimpleTable, AWS::Serverless::StateMachine — each expands into the full underlying resources (Lambda function + execution role + permissions, etc.) at deploy time
sam initScaffold a new project from a starter template
sam buildInstalls dependencies and packages each function's artifacts (in a Docker container matching the Lambda runtime, for compiled dependencies)
sam local invokeRuns a function locally in a Docker container emulating the Lambda runtime, against a supplied test event
sam local start-apiSpins up a local API Gateway emulator in front of your functions for end-to-end local testing
sam deploy --guidedInteractive first deploy — uploads artifacts, packages the template, calls CloudFormation, and saves choices to samconfig.toml
sam syncFast iterative dev loop — pushes code changes directly, bypassing a full stack update, for rapid feedback
sam logsTails CloudWatch Logs for a deployed function
2.8 AWS CDK — Constructs, Apps & CLI High exam relevance
AppThe root construct — contains one or more Stacks
StackUnit of deployment — maps 1:1 to a real CloudFormation stack
L1 constructCfn*-prefixed, auto-generated, 1:1 mapping to a raw CloudFormation resource — no opinionated defaults, you configure every property yourself
L2 constructHand-curated, higher-level wrapper with sensible defaults and helper methods (e.g. bucket.grantRead(role)) — still synthesizes to the same underlying resources as L1
L3 construct (pattern)Bundles multiple resources into one opinionated architecture in a single call — e.g. ApplicationLoadBalancedFargateService provisions the service, task definition, and ALB together
cdk synthRuns your app code, emits CloudFormation template(s) + cloud assembly into cdk.out — deploys nothing
cdk diffCompares the deployed stack against your current code — a change-set-style preview before deploying
cdk deploySynthesizes, uploads assets, then deploys via CloudFormation
cdk bootstrapOne-time per account/Region setup — creates the CDK Toolkit stack (S3 staging bucket, ECR repo, IAM deployment roles); required before the first cdk deploy
cdk destroyDeletes the stack
AssetsLocal files (Lambda code, Docker images) CDK automatically stages to the bootstrap S3 bucket / ECR repo

AWS Exam Thinking

Requirement → Keywords → Expected Answer → why every distractor fails.

Preview whether an update will destroy/replace a stateful resource
preview changesbefore applyingavoid replacement
Expected Answer

Create and review a CloudFormation change set

DistractorWhy it's wrong
Enable drift detectionDetects manual out-of-band changes already made — not a preview of an upcoming update
Just run update-stack and watch the eventsReactive, not preventive — by the time you see it in events the change may already be happening
sam local invokeTests function code locally — unrelated to previewing infrastructure changes
Detect a resource manually changed outside CloudFormation
out-of-band changeconsole drift
Expected Answer

CloudFormation drift detection

DistractorWhy it's wrong
Change setPreviews a future update you're about to make — doesn't audit changes that already happened
AWS ConfigCan track configuration history/compliance generally, but is not the CloudFormation-native mechanism the exam wants here
CloudTrailLogs the API call that made the change, but doesn't compare it against the template's expected state
Team wants imperative, testable, reusable infra code across dozens of stacks
loops/conditionalsreuse across stacksunit-testable infra
Expected Answer

AWS CDK

DistractorWhy it's wrong
AWS SAMDeclarative YAML — no real programming constructs for large-scale reuse or unit testing
Raw CloudFormationWould require heavy copy-paste or a hand-built templating layer to achieve what CDK gives natively
CloudFormation Macros aloneCan generate template fragments, but is a much heavier, lower-level tool than just using CDK directly
Small team, pure serverless app, wants fast local testing
Lambda + API Gateway + DynamoDBlocal testingsimple, declarative
Expected Answer

AWS SAM

DistractorWhy it's wrong
AWS CDKViable, but adds a programming-language learning curve this small serverless-only team doesn't need
Raw CloudFormationNo sam local invoke/start-api equivalent — local testing has to be built manually
Elastic BeanstalkManages an application environment, not a fine-grained serverless resource graph
Reuse a VPC pattern as a building block inside several other stacks (no independent lifecycle)
reusable child templatecomposed into parent
Expected Answer

Nested stack

DistractorWhy it's wrong
Cross-stack export/importBest for independently-lifecycled stacks sharing a few values — not tight composition
StackSetsSolves multi-account/Region replication, not in-account modular reuse
Copy-paste the VPC resources into every stackWorks, but violates DRY and is exactly what nested stacks exist to avoid
Ensure a production RDS instance survives an accidental stack deletion
protect stateful resourcestack deletion
Expected Answer

DeletionPolicy: Retain on the RDS resource (plus Termination Protection on the stack as a second layer)

DistractorWhy it's wrong
UpdateReplacePolicy: RetainOnly protects the resource during a replacement caused by an update — not a full stack deletion
Stack PolicyRestricts update actions only — has no effect on a stack delete operation
Enable drift detectionPurely observational, provides zero protection against deletion
Recover a stack stuck in UPDATE_ROLLBACK_FAILED
stuck rollbackcan't roll back cleanly
Expected Answer

ContinueUpdateRollback (optionally skipping the problem resource)

DistractorWhy it's wrong
Delete and recreate the whole stackDestructive and unnecessary — loses every other resource's state for one stuck resource
Retry UpdateStack immediatelyFails again — the stack must leave the rollback-failed state first
Disable termination protectionUnrelated to rollback state entirely
Deploy the same baseline resources across 50 accounts and 3 Regions centrally
multi-accountmulti-Regioncentralized deployment
Expected Answer

AWS CloudFormation StackSets

DistractorWhy it's wrong
Nested stacksScoped to a single stack/account — no cross-account or cross-Region mechanism
Manually deploy the same template 150 times (50 accounts × 3 Regions)Technically possible, operationally unmanageable and error-prone — exactly what StackSets automates
A single CDK app with one stackOne stack still deploys to one account/Region per deployment — CDK doesn't remove the need for a multi-account/Region distribution mechanism
Locally test a Lambda function that lives inside a CDK app, without rewriting it in SAM
CDK-defined LambdaSAM CLI local testing
Expected Answer

sam build / sam local invoke against the synthesized CDK cloud assembly — the SAM CLI's local-testing tooling isn't exclusive to SAM templates

DistractorWhy it's wrong
Rewrite the entire app in SAMUnnecessary — throws away working CDK code to gain a capability SAM CLI already supports against CDK output
"Impossible — you must pick one tool exclusively"False; this integration is exactly the scenario being tested
Deploy after every change and test in the consoleSlow, defeats the point of a fast local feedback loop

Integrations & Architecture Example

Related Services

AWS CodePipeline / CodeBuild / CodeDeploy
WhatCI/CD services that run cdk synth/sam build and drive the CloudFormation deploy step automatically on every commit
WhyTurns IaC from a manual local command into a repeatable, reviewed pipeline stage
Deeper reading02 — CI/CD Guide
Amazon S3 & Amazon ECR
WhatS3 stores uploaded templates and Lambda code assets; ECR stores container image assets for CDK/SAM container-based Lambdas or Fargate tasks
WhyCloudFormation, SAM, and CDK all need somewhere to stage the actual code/image bytes referenced by the template
IAM
WhatA CloudFormation service role scopes exactly what the stack is allowed to create/modify, separate from the identity that triggers the deployment
WhyLets a CI/CD pipeline (or a developer) trigger deployments without holding broad IAM permissions directly
AWS Lambda
WhatBacks SAM's AWS::Serverless::Function, and also powers Custom Resources — a Lambda-backed resource type that lets CloudFormation manage things it doesn't natively support
WhyCustom Resources are the standard escape hatch when no native CloudFormation resource type exists yet for something you need
AWS Systems Manager Parameter Store & Secrets Manager
WhatDynamic references (e.g. {{resolve:secretsmanager:...}}) pull values into a template at deploy time instead of hardcoding them
WhyThe correct alternative to NoEcho parameters for actual secrets — NoEcho only hides console display, it doesn't encrypt anything
Amazon API Gateway, Amazon Cognito, Amazon DynamoDB
WhatCommon SAM/CDK-defined resources in a serverless app: HTTP API + Cognito authorizer + DynamoDB table alongside the Lambda function
WhyThe typical serverless stack most SAM/CDK exam scenarios describe end-to-end
Amazon CloudWatch
WhatStack events feed CloudWatch; rollback triggers are CloudWatch Alarms attached to a deployment
WhyLets a deployment automatically roll back if a post-deploy metric (e.g. error rate) breaches a threshold, not just on a hard CloudFormation failure

End-to-End Architecture Example

CDK-Authored Serverless API, Deployed via Pipeline Across Environments

A team builds an order-processing API as a single CDK Stack class (TypeScript), parametrized by environment (dev/test/prod) via CDK context/environment settings. A developer pushes code to the source repository, which triggers CodePipeline. A CodeBuild stage runs cdk synth, producing a CloudFormation template plus a Lambda code asset, which CDK stages to the account's bootstrap S3 bucket (created once via cdk bootstrap). CodePipeline's CloudFormation deploy action then creates a change set against the target environment's stack and executes it — provisioning an HTTP API in Amazon API Gateway, a Lambda function as the backend, and a DynamoDB table for persistence, with a Cognito User Pool authorizer protecting the API and X-Ray tracing enabled end-to-end. If the deployment's CloudWatch Alarms (e.g. Lambda error rate) breach their threshold shortly after go-live, a configured rollback trigger automatically rolls the stack back to the previous known-good state — all without anyone hand-running aws cloudformation update-stack in a terminal.

See 08 — Cross-Service Architectures for this pattern drawn out in full alongside four other realistic architectures, and 09 — Hands-On Lab to build a version of it yourself with sam deploy --guided and cdk deploy.

Best Practices & Common Exam Traps

When to Use Each Tool

Raw CloudFormation
  • Use when: you need maximum portability, no extra tooling dependency, or the simplest possible case (a handful of resources)
  • Don't use when: you need heavy reuse across many similar stacks, or fast local testing of serverless code — you'll be hand-rolling what SAM/CDK give for free
AWS SAM
  • Use when: the app is purely (or mostly) serverless, the team wants to stay declarative, and fast local testing (sam local invoke) matters
  • Don't use when: the app spans a lot of non-serverless infrastructure (VPCs, EC2 fleets, complex networking) — SAM's shorthand doesn't help there, you're back to plain CloudFormation resources anyway
AWS CDK
  • Use when: the team wants a real programming language, needs to reuse patterns across many stacks/teams, or wants unit-testable infrastructure
  • Don't use when: the team has no programming-language buy-in and just needs one or two straightforward stacks — the tooling/build overhead isn't worth it

CloudFormation vs SAM vs CDK

AspectCloudFormationSAMCDK
Authoring styleDeclarative JSON/YAMLDeclarative YAML/JSON + serverless shorthandImperative — real programming language
Best forSimplest/most portable cases, any resource typeServerless apps (Lambda, API Gateway, DynamoDB, Step Functions)Any resource type, complex/large-scale infra, heavy reuse
Under the hoodIs the CloudFormation templateCloudFormation + Transform macro that expands shorthand resourcesCompiles ("synthesizes") to a CloudFormation template
Local testingNone built insam local invoke, sam local start-apiVia SAM CLI against the synthesized cloud assembly, or CDK's own assertions/unit-test module
Learning curveLow — just YAML/JSON syntaxLow — YAML/JSON plus a handful of SAM conceptsHigher — requires proficiency in the chosen programming language
Reuse across stacksManual (nested stacks, copy-paste)Manual, same as CloudFormationNative — classes, packages, npm/PyPI-published construct libraries

Common Exam Traps

MisconceptionReality
"SAM and CDK deploy resources directly, bypassing CloudFormation"Both hand off to CloudFormation, which is the actual provisioning engine in every case
"cdk synth deploys my stack"cdk synth only produces the template locally — nothing is deployed until cdk deploy runs
"NoEcho: true encrypts the parameter value"It only masks the value in console/CLI output — it is not encryption or a secrets mechanism
"Drift detection will fix drifted resources"It only reports drift (IN_SYNC/MODIFIED/DELETED/NOT_CHECKED) — it never remediates anything
"DeletionPolicy protects a resource from being replaced during an update"That's UpdateReplacePolicy's job specifically — DeletionPolicy governs deletion/removal from the template, not update-driven replacement
"A Stack Policy stops someone from deleting the whole stack"Stack Policies apply only to update actions; Termination Protection is what blocks stack deletion
"Nested stacks and cross-stack exports are interchangeable"Nested stacks are tight composition with no independent lifecycle; cross-stack exports are for loosely-coupled, independently-lifecycled stacks
"CDK L1 constructs are always the wrong choice"L1 is correct whenever a resource/property has no L2 wrapper yet, or you need full raw control — it's not deprecated or discouraged, just lower-level

Memory Anchors

Say it like this
  • "CDK and SAM are two front doors into the same house — CloudFormation."
  • "Synth previews, deploy commits" — for both change sets and cdk synth/cdk deploy.
  • "Change set = before it happens. Drift = after it already happened."
  • "Retain protects from delete. UpdateReplacePolicy protects from replace."
Quick recall list
  • L1 = raw, L2 = curated, L3 = pattern
  • sam buildsam deploy; cdk synthcdk deploy
  • StackSets = many accounts/Regions; nested stacks = one account, tight composition
  • cdk bootstrap = once per account/Region, before the first deploy

Hands-On Lab

Three short, self-contained exercises that put the concepts from the other tabs under your fingers instead of just in your head — raw CloudFormation, then SAM, then CDK, all deploying to the same underlying engine. All commands target the eu-west-1 (Ireland) Region and use AWS CLI v2. Clean up each exercise's stack when you're done to avoid ongoing charges (the resources used here are all within the AWS Free Tier for light use, but SNS/S3 are not free to leave running indefinitely at scale).

Lab 1 — Raw CloudFormation: Deploy, Change Set, and a Real Rollback

Author a small template by hand, deploy it, preview a modification with a change set, then deliberately break an update so you can watch CloudFormation's automatic rollback happen in front of you.

mkdir cfn-lab && cd cfn-lab

Create template.yaml:

AWSTemplateFormatVersion: '2010-09-09'
Description: DVA-C02 Lab 1 - S3 bucket + SNS topic

Parameters:
  BucketNameSuffix:
    Type: String
    Description: Unique suffix to avoid global S3 name collisions

Resources:
  LabBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "dva-lab-${BucketNameSuffix}"
      VersioningConfiguration:
        Status: Enabled

  LabTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: dva-lab-topic
      DisplayName: DVA Lab Notifications

Outputs:
  BucketArn:
    Description: ARN of the lab bucket
    Value: !GetAtt LabBucket.Arn
  TopicArn:
    Description: ARN of the lab topic
    Value: !Ref LabTopic
    Export:
      Name: dva-lab-topic-arn
  1. Deploy the stack for the first time using aws cloudformation deploy, which internally creates and executes a change set for you:
    aws cloudformation deploy \
      --region eu-west-1 \
      --template-file template.yaml \
      --stack-name dva-lab-1 \
      --parameter-overrides BucketNameSuffix=$(date +%s) \
      --capabilities CAPABILITY_NAMED_IAM
    Stack dva-lab-1 reaches CREATE_COMPLETE; the CLI prints "Successfully created/updated stack".
  2. Confirm the outputs were populated:
    aws cloudformation describe-stacks \
      --region eu-west-1 \
      --stack-name dva-lab-1 \
      --query "Stacks[0].Outputs"
    A JSON array showing BucketArn and TopicArn with real ARN values.
  3. Edit template.yaml: add a Tags block to LabTopic (e.g. Tags: [{Key: env, Value: lab}]), then create a change set manually instead of deploying directly:
    aws cloudformation create-change-set \
      --region eu-west-1 \
      --stack-name dva-lab-1 \
      --change-set-name add-tags-cs \
      --template-body file://template.yaml \
      --parameters ParameterKey=BucketNameSuffix,UsePreviousValue=true
    Change set is created in CREATE_PENDING then CREATE_COMPLETE status — nothing in the live stack has changed yet.
  4. Review exactly what the change set will do before committing to it:
    aws cloudformation describe-change-set \
      --region eu-west-1 \
      --stack-name dva-lab-1 \
      --change-set-name add-tags-cs \
      --query "Changes[].ResourceChange.{Action:Action,Resource:LogicalResourceId,Replacement:Replacement}"
    Shows Action: Modify on LabTopic with Replacement: False — an in-place update, safe to execute.
  5. Execute the change set:
    aws cloudformation execute-change-set \
      --region eu-west-1 \
      --stack-name dva-lab-1 \
      --change-set-name add-tags-cs
    Stack transitions through UPDATE_IN_PROGRESS to UPDATE_COMPLETE.
  6. Now break it on purpose: edit template.yaml and set BucketName: !Sub "dva-lab-${BucketNameSuffix}" to a hardcoded name that already exists globally (e.g. reuse a well-known bucket name like aws-cloudtrail-logs-123456789012, which belongs to another account), then deploy directly:
    aws cloudformation deploy \
      --region eu-west-1 \
      --template-file template.yaml \
      --stack-name dva-lab-1 \
      --parameter-overrides BucketNameSuffix=$(date +%s) \
      --capabilities CAPABILITY_NAMED_IAM
    The update fails because the bucket name is already taken (a Replacement is required and the new resource can't be created), and the CLI eventually reports the stack rolled back.
  7. Watch the automatic rollback happen in the stack's event stream:
    aws cloudformation describe-stack-events \
      --region eu-west-1 \
      --stack-name dva-lab-1 \
      --query "StackEvents[?contains(ResourceStatus,'ROLLBACK')].{Status:ResourceStatus,Reason:ResourceStatusReason}" \
      --output table
    Events show UPDATE_ROLLBACK_IN_PROGRESS then UPDATE_ROLLBACK_COMPLETE — CloudFormation automatically reverted the stack to the last known-good state with no manual intervention required.
  8. Clean up:
    aws cloudformation delete-stack --region eu-west-1 --stack-name dva-lab-1
    Stack and all its resources (bucket, topic) are removed since neither had a DeletionPolicy: Retain.
⚠️ Why this matters for the exam

Step 6-7 is the single most exam-relevant moment in this lab: it proves CREATE_FAILED/UPDATE_FAILED triggers an automatic rollback with zero human action, and it shows you the actual ResourceStatusReason that scenario questions expect you to diagnose from stack events. It also demonstrates exactly why change sets (steps 3-5) exist — had this failed change been previewed as a change set first, describe-change-set would have flagged the Replacement risk before you ever executed it.

Lab 2 — AWS SAM: Scaffold, Build, Test Locally, Then Deploy

SAM's whole value proposition is the fast local loop before you ever touch CloudFormation. This exercise builds a minimal API Gateway + Lambda app and proves that loop end to end.

  1. Scaffold a new app from a starter template (choose the Hello World Example runtime Python 3.12 when prompted, and accept the default project name):
    sam init --runtime python3.12 --name dva-sam-lab --app-template hello-world
    A dva-sam-lab/ directory is created containing template.yaml, a hello_world/ function directory with app.py, and an events/event.json test event.
  2. Open template.yaml and identify the shorthand SAM resource types:
    Transform: AWS::Serverless-2016-10-31
    Resources:
      HelloWorldFunction:
        Type: AWS::Serverless::Function
        Properties:
          CodeUri: hello_world/
          Handler: app.lambda_handler
          Runtime: python3.12
          Events:
            HelloWorld:
              Type: Api
              Properties:
                Path: /hello
                Method: get
    You can see the same Transform: AWS::Serverless-2016-10-31 line from the Components tab, and one AWS::Serverless::Function resource whose Events block implicitly creates the underlying AWS::Serverless::Api — this single resource expands into a Lambda function, an execution role, an API Gateway REST API, and the permissions wiring them together.
  3. Build the function (packages dependencies, in a Docker container matching the Lambda runtime if native deps are present):
    cd dva-sam-lab
    sam build
    A .aws-sam/build/ directory appears containing the built artifact and a rewritten template pointing at it — nothing has been uploaded or deployed yet.
  4. Test the function locally, without deploying anything, using the generated test event:
    sam local invoke HelloWorldFunction --event events/event.json
    Docker starts a container emulating the Lambda runtime, invokes the handler, and prints a response body like {"message": "hello world"} along with a START/END/REPORT log — confirming the function logic works before any AWS resource exists.
  5. Run the guided first deploy, targeting eu-west-1:
    sam deploy --guided --region eu-west-1
    An interactive prompt asks for a stack name (e.g. dva-sam-lab), confirms the Region, asks whether to allow SAM CLI IAM role creation, then packages and deploys — on completion it prints the deployed HelloWorldApi endpoint URL and saves all your answers to samconfig.toml for future non-interactive sam deploy runs.
  6. Hit the live endpoint to confirm the deployed version matches what you tested locally:
    curl $(aws cloudformation describe-stacks \
      --region eu-west-1 --stack-name dva-sam-lab \
      --query "Stacks[0].Outputs[?OutputKey=='HelloWorldApi'].OutputValue" --output text)
    Same JSON response as the local invoke — proving sam local invoke is a genuinely reliable stand-in for the deployed behavior.
  7. Clean up:
    sam delete --region eu-west-1 --stack-name dva-sam-lab --no-prompts
    The underlying CloudFormation stack, and every resource the AWS::Serverless::Function expanded into, is deleted.
⚠️ Why this matters for the exam

Step 4 is the exact CLI verb the exam expects you to name whenever a scenario says "test a Lambda function locally before deploying" — and step 6 proves why that's trustworthy: the local container and the deployed Lambda run the identical build artifact. Also notice that sam deploy --guided never called aws cloudformation create-stack directly — under the hood it still packages the template and hands it to CloudFormation, exactly like every other authoring tool in this guide.

Lab 3 — CDK: Same Destination, Different Road

This exercise deliberately mirrors Lab 1's simple S3 use case, but authored imperatively in CDK, so you can see with your own eyes that cdk synth produces the same kind of plain CloudFormation template that you hand-wrote in Lab 1.

  1. One-time per account/Region setup (skip if you've already bootstrapped eu-west-1 in this account):
    cdk bootstrap aws://ACCOUNT_ID/eu-west-1
    A CDKToolkit CloudFormation stack is created in eu-west-1, containing a staging S3 bucket, an ECR repository, and the IAM roles CDK uses to deploy — required exactly once before any cdk deploy in this account/Region.
  2. Scaffold a new TypeScript app:
    mkdir cdk-lab && cd cdk-lab
    cdk init app --language typescript
    A project is generated with lib/cdk-lab-stack.ts (your Stack class), bin/cdk-lab.ts (the App entry point), and cdk.json pointing at eu-west-1 via your default AWS profile/Region config.
  3. Edit lib/cdk-lab-stack.ts to add one L2 construct — an S3 bucket:
    import * as cdk from 'aws-cdk-lib';
    import { Construct } from 'constructs';
    import * as s3 from 'aws-cdk-lib/aws-s3';
    
    export class CdkLabStack extends cdk.Stack {
      constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
    
        new s3.Bucket(this, 'LabBucket', {
          versioned: true,
          removalPolicy: cdk.RemovalPolicy.DESTROY,
          autoDeleteObjects: true,
        });
      }
    }
    Nine lines of imperative TypeScript — compare this to the ~10 lines of declarative YAML the equivalent bucket took in Lab 1's template. versioned: true is the L2 shorthand for the same VersioningConfiguration: {Status: Enabled} property block you wrote by hand earlier.
  4. Synthesize the CloudFormation template without deploying anything:
    cdk synth
    A full CloudFormation template prints to stdout and is written to cdk.out/CdkLabStack.template.json — no AWS API call to create or update anything has happened yet.
  5. Open cdk.out/CdkLabStack.template.json and find the bucket resource:
    "LabBucket...": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "VersioningConfiguration": { "Status": "Enabled" }
      },
      "UpdateReplacePolicy": "Delete",
      "DeletionPolicy": "Delete"
    }
    A plain AWS::S3::Bucket resource — the exact same resource type you wrote by hand in Lab 1, plus a Custom Resource (Lambda-backed) that CDK auto-generated to implement autoDeleteObjects, since that behavior has no native CloudFormation property.
  6. Preview the diff against what's currently deployed (nothing yet, so everything shows as new):
    cdk diff
    Output lists the stack's IAM changes and resources to be created, formatted like a change-set preview — this is CDK's analogue to aws cloudformation describe-change-set from Lab 1.
  7. Deploy — this synthesizes again internally, uploads assets, then calls CloudFormation:
    cdk deploy --region eu-west-1
    CDK prompts you to approve the IAM/security-related changes, then shows the same kind of CREATE_IN_PROGRESSCREATE_COMPLETE stack events Lab 1's raw aws cloudformation deploy produced, because it's calling the identical underlying API.
  8. Confirm it's a real CloudFormation stack like any other:
    aws cloudformation describe-stacks --region eu-west-1 \
      --stack-name CdkLabStack --query "Stacks[0].StackStatus"
    "CREATE_COMPLETE" — indistinguishable from a stack created via raw CloudFormation or SAM, because it is one.
  9. Clean up:
    cdk destroy --region eu-west-1
    The stack and its bucket are deleted (the DESTROY removal policy + autoDeleteObjects mean the bucket is emptied and removed automatically, rather than blocking deletion the way a non-empty bucket normally would).
⚠️ Why this matters for the exam

Step 5 is the whole point of this lab and of the "Three Tools, One Engine" idea from the Overview tab: when you open the synthesized JSON and see a plain AWS::S3::Bucket resource, you're looking at proof that CDK is not a different deployment mechanism — it's a code generator for the exact same CloudFormation template format Lab 1 used, which is why change sets, drift detection, DeletionPolicy, and rollback behavior all apply to CDK-deployed stacks identically to hand-written ones.

Flashcards — 24 Cards

Click card to flip. Mark right or wrong to track score.

Click to reveal answer
1 / 24
Mark:   Score: 0/0

Practice Quiz — 13 Questions

DVA-C02 scenario style, Easy → Specialty. Select an answer to reveal the explanation.

out of 13 correct