Testing and deployment is 22% of scored content in DVA-C03 (the old Deployment domain at 24%). It has three tasks: preparing artifacts (including container images and API Gateway stages), implementing and automating tests (now with AI tools), and deploying with the AWS CI/CD services including containers. The exam does not ask you to design pipelines from scratch. It asks you to read a buildspec.yml, appspec.yml or SAM template, pick the right deployment strategy, and fix a failing deploy. Learn which tool owns which job and which file configures it.
Preparing application artifacts
Lambda packaging
| Option |
Limit |
Notes |
| .zip upload |
50 MB zipped direct, 250 MB unzipped (code plus layers) |
Upload through console or CLI directly under 50 MB. Larger zips go through S3 |
| Layers |
5 per function, count toward 250 MB |
Shared libraries, SDKs, custom runtimes. Versions are immutable and functions pin a version |
| Container image |
10 GB, from ECR in the same Region |
Use AWS base images or add the Lambda Runtime Interface Client. Test locally with the Runtime Interface Emulator |
- Include dependencies in the package (
npm install, pip install -t) or a layer. Compiled dependencies must match the Lambda architecture (x86_64 or arm64) and Amazon Linux. Build with sam build --use-container to get a compatible environment. Graviton (arm64) is cheaper per ms.
- Keep packages small: cold start grows with size. Remove unused dependencies, bundle and tree-shake (esbuild for Node.js), keep the SDK out if the runtime already provides it.
- Directory structure: handler file at the zip root (or per runtime conventions), dependencies beside it or in
node_modules / python/ layer folders (layers extract to /opt, with nodejs/node_modules or python/ as the expected subfolders).
aws lambda update-function-code deploys code. aws cloudformation package (or sam package) uploads local code to S3 and rewrites template references. sam deploy packages and deploys together.
- Resource needs: choose memory (CPU scales with it) and
/tmp size to fit the workload. For containers on ECS, set task CPU and memory (Fargate has fixed valid combinations) and for EC2 launch types set reservations and limits.
Container images
- Build a Dockerfile, tag the image, authenticate (
aws ecr get-login-password | docker login), then docker push to Amazon ECR. Tags can be mutable or immutable. Use immutable tags or digests for repeatable deploys, never rely on latest.
- ECR features: image scanning (basic or enhanced with Inspector), lifecycle policies to expire old images, cross-Region and cross-account replication, repository policies. A pull failure usually means the task execution role lacks ECR permissions or no route exists to ECR (NAT or VPC endpoints).
- ECS runs containers (Fargate serverless or EC2). A task definition describes images, CPU, memory, ports, env, secrets (from Parameter Store or Secrets Manager) and the task role. A service keeps a desired count running, optionally behind a load balancer, and does rolling or blue/green updates. EKS runs Kubernetes. App Runner is the simplest way to run a web container.
- AWS Copilot CLI scaffolds and deploys containerized apps on ECS and App Runner. It builds a pipeline and environments (
test, prod) for you from commands like copilot init, copilot env deploy, copilot deploy.
Configuration data
| Service |
Use |
| Parameter Store |
Hierarchical configuration and secure strings. Simple and cheap |
| Secrets Manager |
Credentials with rotation |
| AWS AppConfig (part of Systems Manager) |
Feature flags and runtime configuration deployed gradually with validation, monitoring and automatic rollback, without redeploying code |
| Environment variables |
Static settings per function version |
AppConfig concepts: application, environment, configuration profile (the data, with JSON Schema or Lambda validators), deployment strategy (linear, exponential, all-at-once, with bake time), and CloudWatch alarms that roll back a bad deploy. Apps fetch config with the AppConfig Lambda extension or the data plane API (StartConfigurationSession, GetLatestConfiguration) and cache it. Pick AppConfig when a question says “change configuration or toggle a feature for some users, safely, with no deployment”.
- Environment variables (config in the function) force a new function version to change. Parameter Store and AppConfig change without a code deploy.
- Use separate configuration per environment: different Parameter Store paths (
/app/dev/...), different stage variables, different AppConfig environments, never a code branch per environment.
Source control (Git)
- A repo hosts code, IaC,
buildspec.yml, appspec.yml, Dockerfile and tests. Branches isolate work, pull requests gate merges, tags mark releases. A branch can map to an environment (main to production, develop to staging) and triggers the matching pipeline.
- AWS CodeCommit is closed to new customers since mid-2024, so exam scenarios increasingly use GitHub, GitLab or Bitbucket through AWS CodeConnections (formerly CodeStar Connections). The old CodeCommit authentication options were HTTPS Git credentials, SSH keys, or the
git-remote-codecommit helper with IAM roles. Know the commands: git clone, commit, push, branch, merge, tag.
- Use
.gitignore, never commit secrets, keep dependencies out of the repo (restore them in the build).
Testing in development environments
- Lambda versions and aliases: publish a version (immutable). Use aliases such as
dev, test, prod pointing to versions, and invoke by alias ARN. An alias with weighted routing sends, say, 10% to a new version. This is “testing in production” safely and the basis of canary deploys.
- Test events: save JSON payloads in the console (shareable test events), or use
sam local generate-event s3 put and aws lambda invoke --payload. For synchronous CLI invokes with v2, use --cli-binary-format raw-in-base64-out for raw JSON. API Gateway test (console “Test” button) calls a method directly, bypassing authorizers.
- SAM local:
sam local invoke, sam local start-api, sam local start-lambda run functions in a Docker container on your machine. sam sync --watch (SAM Accelerate) pushes changes to the cloud in seconds for development. These require Docker for local runs.
- Mock integration: API Gateway Mock integrations return a canned response with no backend, so front-end teams can test against the API before the backend exists. You can also stub dependencies with mocking libraries in unit tests, or point code at DynamoDB Local or LocalStack.
- Development endpoints: API Gateway stages (
dev, test, prod) each have their own URL, settings, throttling, caching, logging and stage variables. Deploy the same API definition to different stages.
- Deploy to staging:
sam deploy --config-env staging (using samconfig.toml sections) or --stack-name my-app-staging --parameter-overrides Stage=staging deploys the same template to another environment. CloudFormation parameters and mappings make one template serve many environments.
Infrastructure as code
AWS SAM
An open-source framework that extends CloudFormation for serverless apps. A template begins with Transform: AWS::Serverless-2016-10-31.
| SAM resource |
Creates |
AWS::Serverless::Function |
Lambda function, role, event sources, alias and deployment preferences |
AWS::Serverless::Api / HttpApi |
API Gateway REST / HTTP API |
AWS::Serverless::SimpleTable |
DynamoDB table (basic) |
AWS::Serverless::LayerVersion |
Lambda layer |
AWS::Serverless::StateMachine |
Step Functions state machine |
AWS::Serverless::Application |
Nested application from the Serverless Application Repository |
Globals section sets shared defaults. Event sources are declared inline (Events: Type: Api | S3 | SQS | Schedule ...) and SAM generates the permissions.
- Workflow:
sam init then sam build then sam validate then sam local invoke then sam deploy --guided (stores answers in samconfig.toml) then sam logs / sam traces. sam delete removes the stack. SAM policy templates (for example DynamoDBCrudPolicy) give least privilege shortcuts.
- Safe deployments: on a function, set
AutoPublishAlias: live and DeploymentPreference with a Type such as Canary10Percent5Minutes, Linear10PercentEvery1Minute or AllAtOnce, plus Alarms, and Hooks (PreTraffic, PostTraffic Lambda functions). SAM creates the CodeDeploy application and deployment group behind it. If an alarm fires, it rolls back automatically.
- Declarative templates (YAML/JSON) create stacks. Sections:
Parameters, Mappings, Conditions, Resources (the only required one), Outputs, Transform. Intrinsic functions: !Ref, !GetAtt, !Sub, !Join, !FindInMap, !If, !ImportValue.
- Change sets preview changes before execution. Stack rollback: a failed create rolls back by default (
--disable-rollback or OnFailure keeps resources for debugging). A failed update rolls back to the previous state. Drift detection finds manual changes.
- Updating a stack with a changed template,
aws cloudformation deploy, or update-stack. Some property changes need replacement (a new physical resource), which can lose data. DeletionPolicy: Retain/Snapshot protects data.
- Exports/Imports share values across stacks. Nested stacks reuse templates. StackSets deploy to many accounts and Regions.
- Custom resources run a Lambda on create/update/delete. The function must send a response to the presigned URL or the stack waits (and eventually times out).
- Dynamic references pull from Parameter Store and Secrets Manager at deploy time.
AWS CDK
Define infrastructure in TypeScript, Python, Java, C#, Go. Constructs come in three levels: L1 (raw CloudFormation Cfn*), L2 (curated defaults and helper methods such as bucket.grantRead(fn)), L3 (patterns that combine several resources). Commands: cdk init, cdk synth (generates a CloudFormation template), cdk diff, cdk bootstrap (one-time per account and Region: creates the staging bucket and roles), cdk deploy, cdk destroy. CDK always ends up as CloudFormation.
| Tool |
Choose when |
| SAM |
Serverless-focused, simple YAML, local testing, built-in canary deployment |
| CDK |
You want real programming constructs, loops, abstractions |
| CloudFormation |
Direct, all services |
AWS Amplify
Amplify Hosting deploys full-stack web apps (React, Next.js, Vue, and more) from a Git repo with CI/CD. A branch maps to an environment with its own URL (feature branch deployments, preview per pull request). It handles build settings (amplify.yml), custom domains, and rollbacks to a previous build. The Amplify libraries and Gen 2 backend (code-first, TypeScript) provision Cognito, AppSync, DynamoDB, S3 and Lambda for front-end developers.
API Gateway deployment
- Editing an API changes only the draft. You must create a deployment and assign it to a stage before changes are live. “I changed the API but nothing happened” means no redeployment.
- Stages hold stage-level settings and stage variables (name-value pairs like
lambdaAlias=prod) usable in integration URIs, mapping templates and passed to Lambda (event.stageVariables). A common pattern: integrate with myfunction:${stageVariables.lambdaAlias} so dev and prod stages call different aliases. Add Lambda permission for each alias.
- Canary release on a stage sends a percentage of traffic to a new deployment with separate stage variables and settings, then promote or cancel.
- Custom domain names map
api.example.com to a stage using base path mappings (an ACM certificate is required, Route 53 alias record points to the endpoint). Endpoint types: edge-optimized (via CloudFront), Regional, private (VPC only through an interface endpoint).
- Export the API as OpenAPI (Swagger), and import to create one.
CI/CD with AWS services
The pipeline
| Service |
Job |
| CodeCommit (or GitHub, GitLab, Bitbucket via CodeConnections) |
Source |
| CodeBuild |
Build, run tests, package. Managed, per-minute |
| CodeDeploy |
Deploy to EC2, on-premises, Lambda, ECS |
| CodePipeline |
Orchestrate stages. Source, Build, Test, Deploy, Approval |
| CodeArtifact |
Private package repository (npm, pip, Maven, NuGet) with upstream public repos |
| CloudFormation |
Deploy IaC as a pipeline action |
- A change to the watched branch triggers the pipeline (through EventBridge or a webhook). Stages run in order. Actions in a stage run in parallel or by run order. Output artifacts pass between stages through an S3 artifact bucket.
- Manual approval action pauses the pipeline until someone approves or rejects (SNS notification, IAM permission
codepipeline:PutApprovalResult). Automated gates come from tests and alarms.
- Multiple environments: a pipeline stage per environment (dev, test, prod), or a branch-per-environment model. Use the same artifact in each so you promote exactly what was tested.
CodeBuild and the buildspec
buildspec.yml sits at the source root (or is set inline or by path):
version: 0.2
env:
variables: {STAGE: dev}
parameter-store: {DB_URL: /app/db/url}
secrets-manager: {PASS: prod/db:password}
phases:
install: {runtime-versions: {nodejs: 20}}
pre_build: {commands: [npm ci]}
build: {commands: [npm test, npm run build]}
post_build: {commands: [...]}
artifacts:
files: ['**/*']
base-directory: dist
cache:
paths: ['node_modules/**/*']
reports: ...
Phases run in order: install, pre_build, build, post_build. A failed command in a phase stops the build, but post_build still runs (check CODEBUILD_BUILD_SUCCEEDING). artifacts defines what is output, cache speeds later builds (S3 or local), and reports publish test and coverage results. Logs go to CloudWatch Logs. A VPC-configured build needs NAT or endpoints to reach the internet. Docker image builds need privileged mode.
CodeDeploy and the AppSpec
| Compute |
appspec |
Strategies |
| EC2 / on-premises |
appspec.yml with files and hooks (needs the CodeDeploy agent) |
In-place (rolling, per instance), blue/green (new Auto Scaling group, shift load balancer) |
| Lambda |
Names the function, alias, current and target versions |
Canary, linear, all-at-once by alias traffic shifting |
| ECS |
Task definition, container and port |
Blue/green with a load balancer, with canary, linear or all-at-once |
- EC2 in-place hook order:
ApplicationStop → DownloadBundle → BeforeInstall → Install → AfterInstall → ApplicationStart → ValidateService. (Install and DownloadBundle are agent-run and cannot have scripts.) With a load balancer, BeforeBlockTraffic/BlockTraffic/AfterBlockTraffic and BeforeAllowTraffic/AllowTraffic/AfterAllowTraffic wrap these.
- Lambda hooks:
BeforeAllowTraffic and AfterAllowTraffic (functions that run tests, and report back with PutLifecycleEventHookExecutionStatus).
- Deployment configurations for EC2:
AllAtOnce, HalfAtATime, OneAtATime. Lambda: Canary10Percent5Minutes, Linear10PercentEvery1Minute, and so on.
- Rollback: automatic on deployment failure or CloudWatch alarm, or manual. CodeDeploy rolls back by redeploying the last good revision (a new deployment, not an undo). Blue/green keeps the old fleet so traffic can shift back.
- Troubleshooting: agent not running, instance role missing S3 access, wrong hook script permissions or exit code,
appspec.yml not at the bundle root. Agent logs live in /var/log/aws/codedeploy-agent/ and deployment logs under /opt/codedeploy-agent/deployment-root/.
Deployment strategies compared
| Strategy |
How |
Downtime |
Rollback |
Cost |
| All at once |
Replace everything now |
Yes |
Redeploy |
Lowest |
| Rolling |
Batches of instances |
No, reduced capacity |
Redeploy |
Low |
| Rolling with additional batch |
Adds a batch first |
No, full capacity |
Redeploy |
Slightly higher |
| Immutable |
New fleet, swap in when healthy |
No |
Fast (terminate new) |
Higher (double capacity) |
| Blue/green |
Full parallel environment, switch traffic |
No |
Instant (switch back) |
Highest while both run |
| Canary |
Small % first, then the rest |
No |
Fast |
Moderate |
| Linear |
Equal increments on a schedule |
No |
Fast |
Moderate |
Elastic Beanstalk
Platform as a service: you upload code, and it provisions EC2, Auto Scaling, load balancer and health monitoring. You keep control of the resources.
- Deployment policies: All at once, Rolling, Rolling with additional batch, Immutable, Traffic splitting (canary-style, a percentage to new instances for an evaluation time). Blue/green is done by cloning the environment and using Swap Environment URLs (CNAME swap).
.ebextensions/*.config files (YAML/JSON in the bundle) customize the environment: packages, files, commands, option settings, resources. Procfile, platform hooks (.platform/hooks/prebuild|predeploy|postdeploy) and env.yaml also exist. Saved configurations and the EB CLI (eb init, eb create, eb deploy, eb logs, eb swap) manage environments.
- Environment tiers: web server (HTTP) or worker (reads an SQS queue, with an
sqsd daemon posting messages to your app, and cron.yaml for periodic tasks).
- A database inside the Beanstalk environment is deleted with it. For production, create RDS outside the environment. Application versions are stored in S3, with a lifecycle policy to delete old ones.
- Updates to the platform, environment variables and health reporting come from the configuration, not by SSH.
Deploying containerized applications
| Piece |
What to know |
| Dockerfile |
Instructions to build an image: base image, copy code, install dependencies, expose a port, set CMD/ENTRYPOINT. Use multi-stage builds and small base images, run as a non-root user, order layers so rarely changed steps cache |
| Image tagging |
Tag with the Git commit SHA or a version, not just latest. Immutable tags stop an existing tag being overwritten. A digest (sha256:...) pins an exact image |
| ECR lifecycle policy |
Rules that expire images by age or count (for example keep the last 10, expire untagged after 7 days) |
| ECS task definition |
JSON for one or more containers: image, CPU, memory, port mappings, environment, secrets from Parameter Store or Secrets Manager, log configuration, task role and execution role. Each change creates a new numbered revision |
| ECS service |
Keeps N tasks running, registers them with a load balancer target group, and replaces tasks on update |
| Launch types |
Fargate (serverless, you pay per task vCPU and memory, no instances to manage) or EC2 (you manage the cluster, more control, GPUs, cheaper at steady scale) |
| EKS |
Managed Kubernetes. You deploy manifests (Deployment, Service, Ingress, ConfigMap, Secret) with kubectl apply or Helm. Liveness and readiness probes, resource requests and limits, and IAM roles for service accounts apply here |
- Rolling update (ECS default): the service starts new tasks and stops old ones within
minimumHealthyPercent (default 100) and maximumPercent (default 200). A deployment circuit breaker detects tasks that cannot start and rolls back to the last good task definition. EKS Deployments use maxSurge and maxUnavailable and roll back with kubectl rollout undo.
- Blue/green and canary on ECS use CodeDeploy (or the native ECS blue/green) with two target groups and an ALB listener shift.
- CI/CD for containers: CodeBuild builds and pushes the image to ECR, writes an
imagedefinitions.json (or updated task definition and appspec), and CodePipeline deploys it to ECS (ECS standard action or CodeDeploy). Pipeline pushes to Git should trigger it.
- A task that will not start usually points to: image not found or no pull permission (execution role, route to ECR), not enough memory or CPU, a failing health check, or a missing secret permission.
Automated testing and AI-assisted testing
- Validate templates and tests:
sam validate, cfn-lint, aws cloudformation validate-template, CDK assertions (fine-grained and snapshot tests on the synthesized template), and unit tests of handler logic with mocked SDK clients (moved from the development domain: SAM supports local invocation for this). Integration tests call a deployed stage (a test API Gateway stage or a dedicated stack per branch) and then clean up.
- Mock APIs replace external dependencies: API Gateway Mock integrations, a stub Lambda, WireMock-style servers, and SDK stubs. This keeps tests fast, repeatable and free of side effects.
- Test events are JSON payloads in the shape each service sends (API Gateway proxy event, S3 notification, SQS batch, DynamoDB stream record). Store them in the repo for repeatable tests (
sam local generate-event).
- Test in pipeline stages: CodeBuild runs unit tests early, integration or end-to-end tests after a deploy to a test environment, and CodeBuild test reports (JUnit, Cucumber and others) and code coverage reports show results. A failing test action stops the pipeline before production.
- AI tools for testing (for example Kiro and Amazon Q Developer): generate unit tests from code or from a spec, suggest edge cases and negative cases, create test data and mock events, run the test suite in a loop and explain failures, summarize test results, help keep regression tests up to date after a change, and highlight code with weak coverage. Verify that a generated test actually asserts behavior (not just that it runs) and that mocks match the real service contract. AI helps write and run tests. A passing human-reviewed suite in the pipeline is still the gate.
- AI tools in CI/CD: draft approval summaries from a change set or diff (a human still approves production), generate IaC for new environments (SAM, CDK, CloudFormation) for review, suggest pipeline and buildspec fixes from failed logs, and run post-deployment validation (smoke tests, synthetic checks, comparing metrics before and after). Automated approvals are fine for low-risk environments, with manual approval for production.
Rolling back
| Where |
Rollback method |
| Lambda |
Move the alias back to the previous version (or shift weights to 0). Auto rollback with CodeDeploy alarms |
| CodeDeploy |
Automatic on failure or alarm, or redeploy the previous revision. Blue/green: shift traffic back |
| CloudFormation |
Automatic on failed update. Or deploy the previous template. Failed rollback: continue-update-rollback |
| Beanstalk |
Redeploy a previous application version, or swap URLs back |
| API Gateway |
Redeploy a previous deployment to the stage, or cancel the canary |
| ECS |
Update the service to the previous task definition revision (circuit breaker can do it automatically) |
| Amplify |
Redeploy a previous build |
Exam checklist
- “Deploy serverless app with a template”: SAM (
sam build, sam deploy). “Gradual Lambda release with auto rollback”: SAM DeploymentPreference with alarms (CodeDeploy underneath).
- “Share libraries between functions”: layer. “Package over 250 MB”: container image (up to 10 GB).
- “Change a feature flag without redeploying, with rollback”: AppConfig.
- “Different Lambda version per API stage”: stage variable with an alias, and permission for each alias.
- “Changes to API Gateway do not appear”: create a new deployment to the stage.
- “Pipeline must wait for a human”: manual approval action.
- “Build steps and secrets in CodeBuild”:
buildspec.yml with parameter-store / secrets-manager.
- “Hook order for EC2”: ApplicationStop, BeforeInstall, AfterInstall, ApplicationStart, ValidateService.
- “Instant rollback, no impact”: blue/green (Beanstalk swap URLs, CodeDeploy blue/green, Lambda alias).
- “Zero downtime, new instances, easy rollback on Beanstalk”: Immutable (or traffic splitting for a canary).
- “Do not lose RDS data when deleting the Beanstalk env”: create the database outside.
- “Same artifact in every environment”: build once, promote through stages with environment-specific config.
- “Container pull fails in ECS”: task execution role and network path to ECR.
- “Deploy front end from Git with preview per branch”: Amplify Hosting.
- “Private dependency packages”: CodeArtifact.