# AWS Cloud Architecture — Part 14: Elastic Beanstalk, SAM & Developer Tooling

> **Series:** AWS Cloud Architecture (14 of 19)
> **Part 1:** `01-fundamentals-and-account-structure.md` — Fundamentals & Account Structure
> **Part 2:** `02-iam-and-identity.md` — IAM & Identity
> **Part 3:** `03-compute-ec2-and-autoscaling.md` — Compute: EC2 & Auto Scaling
> **Part 4:** `04-networking-vpc-deep-dive.md` — Networking: VPC Deep Dive
> **Part 5:** `05-storage-s3-ebs-efs.md` — Storage: S3, EBS & EFS
> **Part 6:** `06-managed-databases-and-data-services.md` — Managed Databases & Data Services
> **Part 7:** `07-containers-and-serverless.md` — Containers & Serverless
> **Part 8:** `08-load-balancing-cdn-and-dns.md` — Load Balancing, CDN & DNS
> **Part 9:** `09-security-and-compliance.md` — Security & Compliance
> **Part 10:** `10-monitoring-logging-and-tracing.md` — Monitoring, Logging & Tracing
> **Part 11:** `11-cicd-iac-and-messaging.md` — CI/CD, IaC & Messaging
> **Part 12:** `12-multi-region-dr-migration-and-cheatsheet.md` — Multi-Region, DR, Migration & Cheat Sheet
> **Part 13:** `13-api-gateway-integration-and-identity.md` — API Gateway, Cognito & Event Integration
> **Part 14:** This file — Elastic Beanstalk, SAM & Developer Tooling
> **Part 15:** `15-systems-manager-and-fleet-operations.md` — Systems Manager & Fleet Operations
> **Part 16:** `16-cost-optimization-and-finops.md` — Cost Optimization & FinOps
> **Part 17:** `17-migration-and-modernization.md` — Migration & Modernization
> **Part 18:** `18-data-analytics-and-engineering.md` — Data Analytics & Engineering
> **Part 19:** `19-machine-learning-and-ai.md` — Machine Learning & AI on AWS
> **Questions:** `questions.md`

Assumes you're comfortable with EC2/Auto Scaling (Part 3), Lambda (Part 7), and CodePipeline/CloudFormation
(Part 11) — this part is about the layer of tooling a developer actually touches day to day: how code gets
from a laptop to a running service safely, with the smallest amount of undifferentiated setup work.

## Table of Contents

1. [Why This Part Exists](#why-this-part-exists)
2. [Elastic Beanstalk — Managed PaaS, Positioned Against Everything Else in This Series](#elastic-beanstalk--managed-paas-positioned-against-everything-else-in-this-series)
3. [What Elastic Beanstalk Actually Provisions](#what-elastic-beanstalk-actually-provisions)
4. [Supported Platforms and the "Just Upload Code" Model](#supported-platforms-and-the-just-upload-code-model)
5. [Environment Tiers: Web Server vs Worker](#environment-tiers-web-server-vs-worker)
6. [Worker Tier, Worked: Periodic Tasks Without a Separate Scheduler](#worker-tier-worked-periodic-tasks-without-a-separate-scheduler)
7. [Elastic Beanstalk Deployment Policies](#elastic-beanstalk-deployment-policies)
8. [.ebextensions and .platform — Customizing the Managed Environment](#ebextensions-and-platform--customizing-the-managed-environment)
9. [Elastic Beanstalk Environment Types and Swap URLs](#elastic-beanstalk-environment-types-and-swap-urls)
10. [Elastic Beanstalk Health Monitoring and Managed Platform Updates](#elastic-beanstalk-health-monitoring-and-managed-platform-updates)
11. [Cost Shape: Beanstalk Adds No Markup](#cost-shape-beanstalk-adds-no-markup)
12. [Saved Configurations — Reproducing an Environment Deliberately](#saved-configurations--reproducing-an-environment-deliberately)
13. [A Currency Note: Multi-Container Docker Platforms](#a-currency-note-multi-container-docker-platforms)
14. [When Elastic Beanstalk Fits, and When It Doesn't](#when-elastic-beanstalk-fits-and-when-it-doesnt)
15. [Elastic Beanstalk vs App Runner — Two Managed Options, Different Generations](#elastic-beanstalk-vs-app-runner--two-managed-options-different-generations)
16. [Debugging a Failed Elastic Beanstalk Deployment](#debugging-a-failed-elastic-beanstalk-deployment)
17. [AWS SAM — Serverless Application Model, Core Concepts](#aws-sam--serverless-application-model-core-concepts)
18. [The SAM Template — CloudFormation With Serverless Shortcuts](#the-sam-template--cloudformation-with-serverless-shortcuts)
19. [What `sam build`/`sam deploy` Actually Do Under the Hood](#sam-buildsam-deploy-actually-do-under-the-hood)
20. [The SAM CLI Development Loop](#the-sam-cli-development-loop)
21. [Testing Strategy: Unit, Local Integration, and Cloud Integration](#testing-strategy-unit-local-integration-and-cloud-integration)
22. [SAM vs Plain CloudFormation vs CDK — Choosing](#sam-vs-plain-cloudformation-vs-cdk--choosing)
23. [SAM Accelerate and Policy Templates](#sam-accelerate-and-policy-templates)
24. [SAM Nested Applications and the Serverless Application Repository](#sam-nested-applications-and-the-serverless-application-repository)
25. [`sam pipeline` — Bootstrapping CI/CD for a SAM Application](#sam-pipeline--bootstrapping-cicd-for-a-sam-application)
26. [Lambda Deployment Safety: Versions, Aliases, and Weighted Routing](#lambda-deployment-safety-versions-aliases-and-weighted-routing)
27. [CodeDeploy for Lambda: Canary and Linear Traffic Shifting](#codedeploy-for-lambda-canary-and-linear-traffic-shifting)
28. [Automated Rollback on CloudWatch Alarm](#automated-rollback-on-cloudwatch-alarm)
29. [CodeDeploy for API Gateway Too](#codedeploy-for-api-gateway-too)
30. [Pre-Traffic and Post-Traffic Validation Hooks](#pre-traffic-and-post-traffic-validation-hooks)
31. [Choosing a Compute and Deployment Combination](#choosing-a-compute-and-deployment-combination)
32. [Least-Privilege Roles for the Deployment Tooling Itself](#least-privilege-roles-for-the-deployment-tooling-itself)
33. [CodeArtifact — A Managed Package Repository](#codeartifact--a-managed-package-repository)
34. [CodeArtifact Upstream Repositories and Approved-Package Workflows](#codeartifact-upstream-repositories-and-approved-package-workflows)
35. [CodeArtifact Domains — Sharing Repositories Across an Organization](#codeartifact-domains--sharing-repositories-across-an-organization)
36. [Source Control in 2026: Where CodeCommit Actually Stands](#source-control-in-2026-where-codecommit-actually-stands)
37. [CodeGuru: What's Still Active, and What Moved to Amazon Q Developer](#codeguru-whats-still-active-and-what-moved-to-amazon-q-developer)
38. [Managing Sensitive Data in Application Code](#managing-sensitive-data-in-application-code)
39. [AWS CloudShell — The Practical In-Browser Terminal](#aws-cloudshell--the-practical-in-browser-terminal)
40. [Migrating Off an Existing Cloud9 Environment](#migrating-off-an-existing-cloud9-environment)
41. [Cloud9 — Status and Why It's Not the Answer for a New Project](#cloud9--status-and-why-its-not-the-answer-for-a-new-project)
42. [AWS Toolkit IDE Extensions — The Real Cloud9 Replacement](#aws-toolkit-ide-extensions--the-real-cloud9-replacement)
43. [A Full Worked Example: Shipping the Order-Status API Safely](#a-full-worked-example-shipping-the-order-status-api-safely)
44. [Cost Considerations for Developer Tooling](#cost-considerations-for-developer-tooling)
45. [Developer Tooling Best Practices — The Consolidated Checklist](#developer-tooling-best-practices--the-consolidated-checklist)
46. [Part 14 CLI Cheat Sheet](#part-14-cli-cheat-sheet)
47. [Common Mistakes and Interview Traps](#common-mistakes-and-interview-traps)
48. [Worked Practice Problems](#worked-practice-problems)
49. [Summary and What's Next](#summary-and-whats-next)

---

## Why This Part Exists

Part 7 taught EC2, ECS, Fargate, EKS, and Lambda as five different compute shapes, and Part 11 taught the
pipeline tooling (CodeBuild, CodeDeploy, CodePipeline, CloudFormation, CDK) that moves code through them.
What's still missing is the developer-facing layer DVA-C02 spends a quarter of its content on: a
PaaS-style option that removes even more infrastructure decision-making than ECS/Fargate (Elastic
Beanstalk), a framework purpose-built for the serverless slice of Part 7 specifically (SAM), the exact
mechanics of shifting live traffic safely onto a new Lambda version, and the smaller tools (CodeArtifact,
CloudShell) that round out a working day. Think of this part as "Part 11, but for the individual developer
loop" rather than the platform-team pipeline view Part 11 mostly took — the same underlying AWS resources,
seen from the seat of the engineer shipping a single change rather than the team operating the whole
pipeline.

## Elastic Beanstalk — Managed PaaS, Positioned Against Everything Else in This Series

**Elastic Beanstalk** is AWS's oldest "just give us the code" product: upload an application (a ZIP, a
WAR, a container image), and Beanstalk provisions and wires together EC2 instances, an Auto Scaling Group,
an Application Load Balancer, security groups, and CloudWatch alarms — the exact resources Part 3, Part 4,
and Part 8 taught how to build by hand — as one managed unit called an **environment**. The distinguishing
idea, worth stating plainly: **Beanstalk isn't a new compute primitive**, unlike ECS or Lambda — it's an
opinionated automation layer sitting on top of the EC2/ASG/ALB primitives already covered in this series,
which is exactly why understanding Parts 3, 4, and 8 first makes Beanstalk's behavior predictable rather
than magic.

```mermaid
flowchart LR
    Dev["Developer"] -->|"eb deploy /<br/>zip upload"| EB["Elastic Beanstalk<br/>(the automation layer)"]
    EB -->|"provisions"| ASG["Auto Scaling Group<br/>(Part 3)"]
    EB -->|"provisions"| ALB["Application Load Balancer<br/>(Part 8)"]
    EB -->|"provisions"| CW["CloudWatch Alarms<br/>(Part 10)"]
    EB -->|"provisions"| SG["Security Groups<br/>(Part 4)"]

    classDef dev fill:#1d4ed8,stroke:#1e3a8a,color:#ffffff
    classDef eb fill:#7c3aed,stroke:#4c1d95,color:#ffffff
    classDef prim fill:#0f766e,stroke:#134e4a,color:#ffffff
    class Dev dev
    class EB eb
    class ASG,ALB,CW,SG prim
```

## What Elastic Beanstalk Actually Provisions

Every resource Beanstalk creates is a real, visible resource in the account — an ASG a team could find and
inspect in the EC2 console exactly as if they'd built it manually — and every one of those resources is
tagged and managed by Beanstalk, meaning **hand-editing them outside Beanstalk (resizing the ASG directly,
say) will often get silently reverted** the next time Beanstalk reconciles the environment's configuration.
This is the same "don't fight the controller" lesson from GitOps/Kubernetes reconciliation loops, applied
to a PaaS instead of a cluster.

## Supported Platforms and the "Just Upload Code" Model

Beanstalk ships **managed platforms** for Java, .NET, PHP, Node.js, Python, Ruby, Go, and Docker — each a
maintained AMI/container base image with the language runtime, a web server, and OS patches kept current by
AWS. As of mid-2026, AWS has been actively retiring older platform branches (Node.js 20, Python 3.9, and
Ruby 3.2 on Amazon Linux 2023 were retired in August 2026) — a real operational task for any Beanstalk
user is watching platform deprecation notices and upgrading before a retired branch stops receiving
security patches, conceptually identical to the AMI lifecycle discipline Part 3 covers for hand-managed
EC2 fleets.

## Environment Tiers: Web Server vs Worker

A Beanstalk environment is provisioned as one of two tiers: a **Web Server tier** (the default — an ALB in
front of an ASG, handling HTTP traffic directly) or a **Worker tier** (no load balancer or public traffic
at all; instead, the environment polls an SQS queue and invokes the application with each message's
payload, exactly the queue-worker shape Part 11's SQS section already established, just running on
Beanstalk-managed EC2 instead of a hand-built consumer). A background-job-processing application and its
public-facing API frontend are typically deployed as **two separate Beanstalk environments**, one of each
tier, sharing the same application version bundle.

## Worker Tier, Worked: Periodic Tasks Without a Separate Scheduler

A Worker tier environment gets one more capability worth calling out specifically: a `cron.yaml` file in
the application bundle declares periodic tasks (a cron expression plus an HTTP path the environment should
call on that schedule), and Beanstalk itself enqueues those as SQS messages on schedule — no separate
EventBridge Scheduler rule or standalone cron daemon required. This is a narrower, more coupled tool than
EventBridge Scheduler (which can target far more than one Beanstalk worker environment), but for a team
already running a Worker tier environment for its regular queue-consumption work, reusing the exact same
environment for its scheduled jobs avoids standing up and monitoring a second scheduling mechanism.

## Elastic Beanstalk Deployment Policies

| Policy | How it works | Downtime | Rollback speed |
|---|---|---|---|
| **All at once** | Every instance updated simultaneously | Brief outage during deploy | Requires a new deploy |
| **Rolling** | Updates a configurable batch of instances at a time, in place | None, but reduced capacity during rollout | Requires a new deploy |
| **Rolling with additional batch** | Launches a new batch first, then rolls in the same pattern | None, capacity maintained throughout | Requires a new deploy |
| **Immutable** | Launches an entirely new, parallel ASG; only cuts over once healthy | None | Fast — old ASG still exists briefly |
| **Blue/Green (swap)** | Deploys to a completely separate environment, then swaps the CNAME | None | Instant — swap back |

This is the same rolling/immutable/blue-green vocabulary from Part 7's ECS deployment strategies section,
applied to EC2-backed Beanstalk environments — the underlying tradeoffs (speed vs safety vs cost of
double capacity) are identical regardless of which compute layer sits underneath.

## .ebextensions and .platform — Customizing the Managed Environment

A managed platform inevitably needs some customization beyond what the platform provides out of the box —
installing an OS package, writing a config file, running a one-time setup command. `.ebextensions/*.config`
files (YAML, placed in the application source bundle) declare exactly this: packages, files, commands, and
even arbitrary resources (an extra security group, an SNS topic) as CloudFormation snippets merged into the
environment's own stack. The newer `.platform` directory (hooks and Nginx/Apache proxy config) covers the
subset of customization that's platform-lifecycle-specific — pre/post-deploy hooks — rather than
CloudFormation-level resource changes. Both live in source control alongside the application, so a fresh
environment reconstructed from scratch reproduces the exact same customizations — configuration as code,
the same principle Part 11's CloudFormation section already established, scoped to Beanstalk's own
environment model.

## Elastic Beanstalk Environment Types and Swap URLs

A genuinely useful, exam-relevant pattern: create a **second, parallel Beanstalk environment** (same
application, a new version), fully test it against its own separate URL, then use **Swap Environment
URLs** to atomically exchange the CNAMEs between the old and new environments — production traffic moves
to the new environment instantly, and the old one still exists, fully intact, as an instant rollback target
if anything goes wrong post-swap. This is Beanstalk's own native implementation of the blue/green pattern,
and it's the deployment policy DVA-C02 tends to test most directly, precisely because "swap back" is such
an unambiguous, fast rollback compared to the other four policies.

## Elastic Beanstalk Health Monitoring and Managed Platform Updates

Beanstalk's **enhanced health reporting** goes beyond a plain EC2/ALB health check — it aggregates
instance-level OS metrics, request latency, and HTTP status-code distribution into a single per-environment
health color (green/yellow/red/grey) visible in the console and queryable via the API, feeding the same
CloudWatch alarm patterns Part 10 covers. Separately, **managed platform updates** can apply patch-level
platform updates (an OS security patch, a minor runtime version bump) automatically on a maintenance
window, using the same rolling-deployment mechanics from the table above — genuinely useful for keeping a
fleet patched without a person remembering to do it, but worth pairing with a staging environment that
receives updates first, since an automatic minor-version bump can occasionally still break an application
depending on unpinned behavior.

## Cost Shape: Beanstalk Adds No Markup

A detail worth stating plainly, since it's a common point of confusion: **Elastic Beanstalk itself is
free** — there's no separate charge for the orchestration layer. The bill is exactly the sum of the
underlying EC2/ALB/CloudWatch resources it provisions, the same resources Part 3/4/8/10 already priced out
individually. Beanstalk's actual cost tradeoff isn't a line item — it's the operational cost of an extra
abstraction layer to reason about when something behaves unexpectedly, against the setup time it saves
versus hand-building the equivalent stack.

## Saved Configurations — Reproducing an Environment Deliberately

A **saved configuration** captures an environment's full settings (instance type, scaling limits,
environment variables, platform version) as a reusable template, separate from the application code
itself — applying it to a brand-new environment reproduces the exact same configuration without manually
re-entering every setting, and is the standard way to keep a staging environment's configuration
deliberately in sync with production (or, just as usefully, to keep them deliberately *different* in a
tracked, intentional way rather than by accident). This is Beanstalk's lighter-weight answer to the same
"environment reproducibility" goal CloudFormation StackSets (Part 1) provide at the whole-account level.

## A Currency Note: Multi-Container Docker Platforms

Beanstalk's original **Multi-container Docker** platform (running several containers per instance,
coordinated by an Elastic Beanstalk-managed ECS cluster underneath) has been superseded by simply running
workloads on ECS/Fargate directly (Part 7), which now offers equal or better multi-container orchestration
with none of Beanstalk's extra abstraction layer in the way. Any current guidance describing multi-container
Docker as the recommended way to run several containers together on Beanstalk is describing a legacy path —
for a genuinely multi-container workload today, going straight to ECS/Fargate is the more direct, better-
supported choice; Beanstalk's own container support is best reserved for the single-container case.

## When Elastic Beanstalk Fits, and When It Doesn't

| Signal | Favors |
|---|---|
| A team wants EC2-level control (custom AMI tweaks, SSH access) with less setup burden than hand-building an ASG | Elastic Beanstalk |
| The application is already containerized and the team wants orchestration-level control (service mesh, custom scheduling) | ECS/EKS (Part 7) |
| The workload is naturally event-driven and can tolerate cold starts, billed per invocation | Lambda (Part 7) |
| The team needs fine-grained infrastructure-as-code control beyond what a PaaS abstraction exposes | Hand-built EC2/ECS via CloudFormation/CDK (Part 11) |
| A small team wants to deploy an existing monolithic web app with minimal new tooling to learn | Elastic Beanstalk |

Elastic Beanstalk is genuinely still a reasonable choice for the case it was built for — it isn't
"legacy" the way CodeCommit or Cloud9 are — but it's worth being honest that most **new**, container-native
or serverless-native projects reach for ECS/Fargate or Lambda directly rather than Beanstalk today, simply
because those now offer comparable ease of use with fewer abstraction layers to reason about when
something breaks.

## Elastic Beanstalk vs App Runner — Two Managed Options, Different Generations

Part 7 introduced **App Runner** as "an even simpler option" for containerized services. Both Beanstalk
and App Runner exist to remove infrastructure decisions from a developer, but they're genuinely different
generations of that idea, and confusing them is an easy mistake:

| | Elastic Beanstalk | App Runner |
|---|---|---|
| Underlying compute | EC2 instances, visible and inspectable | Fully abstracted — no visible EC2/ASG at all |
| Input | Source bundle (ZIP/WAR) or container image | Container image, or source code built by App Runner itself |
| Scale-to-zero | No — an ASG's minimum capacity always runs | Yes — genuinely scales down when idle |
| Networking customization | Full VPC/security-group control | More limited, VPC connector required for private resources |
| Best fit | Existing EC2-shaped applications, teams wanting inspectable infrastructure | New containerized web services wanting the least possible operational surface |

The practical rule of thumb: a genuinely new, container-native service leans App Runner; an existing
EC2-shaped application (or a team that specifically wants visible, inspectable infrastructure underneath
the abstraction) leans Beanstalk.

## Debugging a Failed Elastic Beanstalk Deployment

A deployment that fails partway through is one of the more common real-world Beanstalk troubleshooting
scenarios, and the diagnostic path is consistent: `eb health` (or the console's enhanced health view) shows
which instances are failing and why at a glance; `eb logs` pulls the actual application and web-server logs
from the failing instances without needing to SSH in manually; and the **events stream**
(`aws elasticbeanstalk describe-events`) shows the exact sequence of what Beanstalk attempted and where it
gave up — commonly a failed `.ebextensions` command, a health check failing before the configured timeout,
or the new application version crashing on startup. Because a rolling or immutable deployment only shifts
traffic to instances that pass health checks, a bad deployment using either of those policies typically
fails safely (old instances keep serving traffic) rather than causing an outage — which is, worth restating,
the whole reason those policies exist over "all at once."

## AWS SAM — Serverless Application Model, Core Concepts

Where Elastic Beanstalk simplifies EC2-based deployment, **AWS SAM (Serverless Application Model)** does
the equivalent for the serverless slice of Part 7 — Lambda, API Gateway, DynamoDB, Step Functions — as an
open-source framework built directly on top of CloudFormation (Part 11), not a replacement for it. A SAM
template **is** a CloudFormation template, using a `Transform: AWS::Serverless-2016-10-31` header that
tells CloudFormation to expand SAM's simplified resource types (`AWS::Serverless::Function`,
`AWS::Serverless::Api`) into the much more verbose plain-CloudFormation resources (a Lambda function, its
IAM role, its API Gateway integration, its permissions) before deploying — meaning everything Part 11
already taught about CloudFormation (stacks, change sets, drift detection) applies to a deployed SAM
application unchanged.

## The SAM Template — CloudFormation With Serverless Shortcuts

```yaml
Transform: AWS::Serverless-2016-10-31
Resources:
  OrderStatusFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: app.handler
      Runtime: python3.13
      Events:
        Api:
          Type: Api
          Properties:
            Path: /orders/{id}
            Method: get
```

That one `AWS::Serverless::Function` resource, once transformed, expands into a Lambda function, an IAM
execution role scoped to what the function actually needs, an API Gateway REST API, a resource/method for
the route, and the Lambda permission granting API Gateway the right to invoke it — five-plus plain
CloudFormation resources' worth of boilerplate collapsed into roughly ten lines of intent.

## What `sam build`/`sam deploy` Actually Do Under the Hood

```mermaid
flowchart TD
    Template["template.yaml<br/>(Serverless:: shortcuts)"] --> Build["sam build<br/>resolves dependencies,<br/>packages each function"]
    Build --> Artifacts[".aws-sam/build/<br/>(deployable artifacts)"]
    Artifacts --> Local{"Test first?"}
    Local -->|"sam local invoke /<br/>start-api"| DockerRuntime["Local Docker container<br/>matching real Lambda runtime"]
    Local -->|"skip"| Deploy["sam deploy"]
    DockerRuntime --> Deploy
    Deploy --> Package["Package: upload artifacts to S3"]
    Package --> Transform["CloudFormation Transform<br/>expands Serverless:: resources"]
    Transform --> Stack["Real CloudFormation stack<br/>(Lambda, IAM role, API Gateway, ...)"]

    classDef file fill:#334155,stroke:#0f172a,color:#ffffff
    classDef action fill:#1d4ed8,stroke:#1e3a8a,color:#ffffff
    classDef decision fill:#7c3aed,stroke:#4c1d95,color:#ffffff
    classDef result fill:#0f766e,stroke:#134e4a,color:#ffffff
    class Template,Artifacts file
    class Build,Deploy,Package,Transform,DockerRuntime action
    class Local decision
    class Stack result
```

## The SAM CLI Development Loop

| Command | What it does |
|---|---|
| `sam init` | Scaffolds a new project from a starter template |
| `sam build` | Resolves dependencies and packages each function into `.aws-sam/build/`, ready for local testing or deploy |
| `sam local invoke` | Runs one function locally, in a Docker container matching the real Lambda runtime, without deploying anything |
| `sam local start-api` | Spins up a local API Gateway emulator, routing to local function invocations — the fast local dev loop for an API-backed function |
| `sam deploy --guided` | Packages artifacts to S3, then deploys the underlying CloudFormation stack, prompting for parameters the first time |
| `sam logs` | Tails a deployed function's CloudWatch Logs from the CLI |

The genuinely valuable piece for a working developer is `sam local` — testing Lambda code against a
realistic runtime environment **before** it ever touches a real AWS account, catching the class of bug
(a missing dependency in the deployment package, a runtime-version mismatch) that only shows up after
deploy with a plain `zip`-and-upload workflow.

## Testing Strategy: Unit, Local Integration, and Cloud Integration

Three distinct testing layers apply to a serverless application, and DVA-C02's "test applications in
development environments" task statement expects knowing which tool fits which layer:

| Layer | Tool | Catches |
|---|---|---|
| **Unit** | A normal test framework (pytest, Jest) with mocked AWS SDK calls | Business logic bugs, independent of any AWS behavior |
| **Local integration** | `sam local invoke`/`start-api` against a real Docker-emulated Lambda runtime | Runtime-version mismatches, missing dependencies, cold-start-shaped bugs |
| **Cloud integration** | A deployed test/staging stage (often via `sam sync` for fast iteration), hitting real AWS services | IAM permission gaps, real service quotas/limits, actual latency and cross-service behavior that no emulator fully replicates |

Each layer catches a different class of bug, and skipping straight from unit tests to production is the
common, costly mistake — an IAM policy that's subtly too narrow, for instance, passes every unit test and
every local `sam local` invocation (which doesn't enforce real IAM at all) and only fails once genuinely
deployed against a real, permission-checked AWS account.

## SAM vs Plain CloudFormation vs CDK — Choosing

| | Plain CloudFormation | SAM | CDK |
|---|---|---|---|
| Language | YAML/JSON only | YAML/JSON, with serverless shortcuts | Real programming language (TypeScript, Python, Java, ...) |
| Best fit | Any AWS resource, maximum explicitness | Serverless-heavy applications, local Lambda testing | Complex logic, reusable constructs, non-serverless infra too |
| Local testing | None built in | `sam local` | None built in (synthesizes to CloudFormation, same as plain) |
| Under the hood | Itself | Transforms to CloudFormation | Synthesizes to CloudFormation |

All three ultimately produce and deploy CloudFormation stacks — the choice is about authoring ergonomics
and local-testing needs, not about a difference in what gets deployed underneath. A team already committed
to CDK for its broader infrastructure (Part 11) can still reasonably keep using CDK for Lambda-heavy
stacks too; SAM's specific edge is the `sam local` testing loop, which CDK doesn't provide natively.

## SAM Accelerate and Policy Templates

Two SAM features worth knowing specifically because they solve real, common pain points. **SAM Accelerate**
(`sam sync`) closes the gap between `sam local`'s fast-but-imperfect emulation and a full `sam deploy`'s
accuracy-but-slowness: it syncs code changes directly to the actual deployed Lambda functions/API Gateway
resources in a development account, skipping a full CloudFormation stack update for a code-only change —
genuinely useful for the "test against real AWS behavior, not an emulator, without a two-minute deploy every
time" iteration loop. **Policy templates** are a curated library of least-privilege IAM policy snippets
(`DynamoDBCrudPolicy`, `S3ReadPolicy`, `SQSPollerPolicy`) referenced by name in a SAM template's function
definition, expanding into a correctly-scoped IAM policy automatically — removing an entire category of
either "way too permissive" or "hand-crafted and subtly wrong" IAM policies that would otherwise get
written by hand for every new function, tying directly back to Part 2's least-privilege principle.

## SAM Nested Applications and the Serverless Application Repository

A SAM template can reference another, entirely separate SAM application as a **nested application** —
either one published privately within an organization or a public one from the **Serverless Application
Repository (SAR)**, a catalog of pre-built, reusable serverless applications (an S3-to-Slack notifier, a
CloudWatch-alarm-to-PagerDuty bridge). Consuming a SAR application is a single `AWS::Serverless::Application`
resource pointing at its ARN, with parameters passed the same way a Terraform module or CDK construct
accepts them — a real building-block pattern for common, well-solved integration glue that a team would
otherwise reimplement from scratch. The same mechanism lets a platform team publish its own internal
"golden path" serverless patterns (Part 1's landing-zone-equivalent idea, applied to application
architecture instead of account structure) for other teams to consume as a nested application rather than
copy-pasting a template.

## `sam pipeline` — Bootstrapping CI/CD for a SAM Application

Beyond the individual-developer loop, `sam pipeline bootstrap` and `sam pipeline init` generate a working
CodePipeline (or GitHub Actions/GitLab CI) configuration for a SAM application, wired to deploy through
multiple stages (test, staging, production) with the correct cross-account IAM roles already scoped
per-stage — the SAM-specific shortcut for exactly the multi-account pipeline pattern Part 1 and Part 11
already established as the general best practice. This matters because a serverless application's
pipeline needs are rarely different in kind from any other application's (build, test, deploy through
environments, Part 11's whole subject) — `sam pipeline` just removes the boilerplate of wiring that
scaffolding by hand for the common serverless case specifically.

## Lambda Deployment Safety: Versions, Aliases, and Weighted Routing

Every Lambda deployment publishes an immutable **version** (a numbered, frozen snapshot of code and
configuration). An **alias** is a named, mutable pointer at one or more versions — `prod` might point
entirely at version 12, or be configured to route **90% of invocations to version 12 and 10% to version
13**, exactly the weighted-traffic-shifting idea from Part 8's load balancer target groups, expressed at
the function-alias level instead. Client code (API Gateway, EventBridge, another service) should always
invoke the **alias ARN**, never a specific version ARN directly — that indirection is what makes traffic
shifting possible without reconfiguring every caller on every release.

## CodeDeploy for Lambda: Canary and Linear Traffic Shifting

CodeDeploy (Part 11) doesn't just deploy to EC2/ECS — it manages exactly this alias-weight shifting for
Lambda deployments, using the same deployment-configuration vocabulary:

```mermaid
sequenceDiagram
    participant Dev as CI/CD Pipeline
    participant CD as CodeDeploy
    participant Alias as prod alias
    participant Old as Version 12
    participant New as Version 13
    participant CW as CloudWatch Alarm

    Dev->>CD: Deploy version 13
    CD->>Alias: Shift 10% traffic to v13 (Canary10Percent5Minutes)
    Alias->>New: 10% of invocations
    Alias->>Old: 90% of invocations
    CD->>CW: Monitor error-rate alarm
    CW-->>CD: Healthy after 5 minutes
    CD->>Alias: Shift 100% traffic to v13
    Alias->>New: 100% of invocations
```

| Configuration | Shape |
|---|---|
| `AllAtOnce` | 100% immediately — fastest, no gradual safety net |
| `Canary10Percent5Minutes` | 10% for 5 minutes, then 100% |
| `Linear10PercentEvery1Minute` | +10% every minute until 100% |

Canary and linear configurations exist in several preset percentage/interval combinations — the choice is
a direct tradeoff between how fast a bad deploy gets fully exposed to traffic versus how long a rollout
takes to complete.

## Automated Rollback on CloudWatch Alarm

The real safety value isn't the gradual shift alone — it's pairing it with a **CloudWatch alarm** (Part
10) on the function's error rate or duration. If the alarm trips during any shift stage, CodeDeploy
automatically halts the rollout and **shifts the alias back to the previous version**, with zero manual
intervention — the Lambda-specific instance of the same "alarm-triggered automatic rollback" pattern
covered for ECS deployments in Part 7. Configuring this alarm is not optional in any serious production
setup: a canary shift with no attached alarm just delays a bad deploy's full blast radius by a few minutes
rather than actually preventing it.

## CodeDeploy for API Gateway Too

The same canary/linear traffic-shifting mechanism, less commonly discussed but real: a REST API's **stage
canary** (introduced in Part 13) can be driven by the same kind of gradual percentage shift, with its own
independent CloudWatch metrics for the canary vs. baseline deployment — meaning a full request path
(API Gateway stage canary feeding a Lambda alias canary) can be rolled out with two independent, layered
safety nets rather than one.

## Pre-Traffic and Post-Traffic Validation Hooks

A CodeDeploy-managed Lambda deployment can run **`Hooks`** — themselves Lambda functions — immediately
before shifting any traffic (`PreTraffic`) and immediately after reaching 100% (`PostTraffic`). A
`PreTraffic` hook invoking the new version directly with a synthetic test payload and calling back
`PutLifecycleEventHookExecutionStatus` with a pass/fail verdict is the standard pattern for catching an
obviously broken deployment (a missing environment variable, a crash on cold start) **before it ever
receives a single unit of real traffic** — a stronger guarantee than a canary alone provides, since even a
10% canary still means some real requests hit genuinely broken code for a few minutes.

## Choosing a Compute and Deployment Combination

Pulling Part 7's compute options and this part's deployment mechanisms into one decision:

| Compute choice | Deployment mechanism | Fits |
|---|---|---|
| EC2 (hand-built ASG) | CodeDeploy in-place or blue/green (Part 11) | Maximum control, existing non-containerized workloads |
| Elastic Beanstalk | Beanstalk deployment policies, swap-URL blue/green | Less setup than hand-built EC2, still EC2-based |
| ECS/Fargate | ECS rolling or blue/green via CodeDeploy (Part 7) | Containerized services wanting orchestration |
| Lambda | Alias weighting via CodeDeploy canary/linear | Event-driven, serverless-first workloads |

Every row uses the same underlying safety idea — shift traffic gradually, watch a real health signal, roll
back automatically — expressed through whichever mechanism that compute layer natively supports.

## Least-Privilege Roles for the Deployment Tooling Itself

Every tool in this part runs under its own IAM role, and scoping those roles correctly is squarely within
DVA-C02's Security domain, not just an operational nicety. Beanstalk's **service role** (what Beanstalk
itself uses to manage resources) and its **instance profile** (Part 2 — what the running application code
uses) are two genuinely separate roles serving different purposes, and conflating them — granting the
instance profile Beanstalk's own management-level permissions — hands every request handled by the running
application far more privilege than it needs. The same discipline applies to CodeBuild/CodeDeploy service
roles (Part 11): a SAM deployment's CodeBuild role needs permission to package and deploy the **specific**
stack it owns, not blanket `cloudformation:*`/`iam:*` across the account — the same least-privilege
principle from Part 2, applied to the pipeline's own identity rather than a human's.

## CodeArtifact — A Managed Package Repository

**CodeArtifact** is a managed artifact repository for the packages an application actually depends on —
npm, PyPI, Maven, NuGet, and generic packages — solving the same problem a self-hosted Artifactory/Nexus
instance solves, without the operational burden of running one. Beyond simple hosting, CodeArtifact acts
as a **caching proxy** in front of public registries (npm Registry, PyPI, Maven Central): a build pulling a
public dependency through CodeArtifact gets it cached locally after the first fetch, which is both a
resilience win (a public registry outage no longer blocks every build) and, combined with IAM policies
restricting which packages/versions are pullable, a real **software-supply-chain control point** — the
same "don't trust upstream blindly" instinct behind image scanning (Part 9) applied to language-ecosystem
dependencies instead of container images.

## CodeArtifact Upstream Repositories and Approved-Package Workflows

Repositories can be chained: an internal `company-npm` repository with an **upstream** pointing at the
public npm registry, itself consumed by team-specific repositories further downstream. Combined with
CloudTrail (Part 9) and EventBridge (Part 13), an organization can build an approval gate — a new version
of a public package only becomes available to internal teams after passing an automated or manual review,
without blocking every developer from ever pulling anything new at all. This is the practical mechanism
behind "vet dependencies before they reach production code," a control auditors specifically look for in
supply-chain-security reviews.

## CodeArtifact Domains — Sharing Repositories Across an Organization

A **domain** groups multiple CodeArtifact repositories under one umbrella for organization-wide asset
sharing and, critically, **deduplicated storage and consistent access control** — every repository in a
domain shares the same underlying package storage, so the same version of a common dependency isn't stored
redundantly per team. A domain's resource policy can grant read access to repositories from other AWS
accounts entirely, the same cross-account resource-policy pattern already familiar from S3 bucket policies
(Part 5) and KMS key policies (Part 9) — letting a central platform team own and curate a shared,
organization-wide set of approved package versions that every application account consumes read-only,
without duplicating the artifact storage or the approval workflow per account.

## Source Control in 2026: Where CodeCommit Actually Stands

Worth stating clearly and accurately, since training data on this point goes stale fast: **AWS CodeCommit
stopped onboarding new customers in mid-2024** and is not gaining new features going forward — existing
CodeCommit users can keep using it, but AWS's own current guidance for anyone starting fresh is to use
GitHub, GitLab, Bitbucket, or another third-party Git host, with CodePipeline/CodeBuild (Part 11) or
CodeCatalyst integrating directly against those instead. This series' Part 11 already treated CodeCommit as
a brief, secondary note rather than the default recommendation — this part just makes the reasoning
explicit: for any **new** project today, pick a third-party Git host and connect it to CodePipeline via a
CodeStar Connection, not CodeCommit.

## CodeGuru: What's Still Active, and What Moved to Amazon Q Developer

Another point where currency matters: **CodeGuru Reviewer moved to maintenance mode in November 2025** —
no new repository associations can be created, though existing ones keep working. For a new project, AWS's
own current guidance routes automated code review (static analysis, secrets detection, dependency
vulnerability scanning) to **Amazon Q Developer** instead, and code security scanning specifically to
**Amazon Inspector** (Part 9's code-scanning capability, expanded). **CodeGuru Profiler**, by contrast,
remains actively supported and is the still-current tool for its distinct job: continuous, low-overhead
CPU/latency profiling of a running application in production, surfacing exactly which function calls are
actually burning CPU time or driving up p99 latency — a genuinely different problem than static code
review, and one Q Developer doesn't replace. Under the hood, the Profiler agent samples the application's
running call stack at a low, configurable frequency (deliberately cheap enough to run continuously in
production without materially affecting latency), then aggregates those samples into a **flame graph** and
a set of automated **recommendation reports** — flagging patterns like excessive garbage collection, a hot
loop doing redundant work, or blocking I/O on a thread that shouldn't be blocking, all without a developer
needing to manually instrument the code with timers first. This is a genuinely different diagnostic layer
from X-Ray (Part 10): X-Ray answers "which service in a distributed call chain is slow," while Profiler
answers "which specific function, inside one already-identified service, is actually burning the CPU."

## Managing Sensitive Data in Application Code

Part 9 covered Secrets Manager and Parameter Store as services; the developer-facing question DVA-C02
tests directly is **how application code should actually consume them**. The pattern that holds up in
practice: fetch the secret at cold start (or via a short-lived in-memory cache with a sensible TTL), never
bake it into an environment variable set at deploy time and never commit it to the source bundle at all —
an environment variable is visible to anyone with read access to the function/environment's configuration,
which is a materially weaker boundary than an IAM-gated Secrets Manager `GetSecretValue` call logged to
CloudTrail. For Lambda specifically, the **Secrets Manager Lambda extension** (a layer providing a local
caching HTTP endpoint inside the execution environment) avoids paying Secrets Manager's API latency and
cost on every single invocation, while still never persisting the secret to disk or to a long-lived
environment variable. Beanstalk environment properties, by contrast, **are** just environment variables
under the hood — fine for non-sensitive configuration (a feature flag, a log level), never the place for an
actual credential.

## AWS CloudShell — The Practical In-Browser Terminal

**CloudShell** is a browser-based shell, launched straight from the AWS Console, pre-authenticated with the
console session's own credentials and pre-installed with the AWS CLI, plus common language runtimes
(Python, Node.js) and Git. It's genuinely useful for exactly what it's built for: a quick CLI command from
a machine that doesn't have the AWS CLI configured, or a fast one-off script during an incident, without
provisioning anything. It is **not** a persistent development environment — its home directory persists per
region, but the underlying compute is ephemeral and there's no reasonable way to run a long-lived background
process, a full IDE, or a debugger against it.

## Migrating Off an Existing Cloud9 Environment

For a team still running Cloud9 today, migrating isn't urgent (existing environments keep working and keep
receiving security patches), but it's worth planning deliberately rather than reactively: the practical
path is installing the AWS Toolkit extension in VS Code or a JetBrains IDE, pointing it at the same AWS
account/region the Cloud9 environment used, and confirming the team's usual `sam local`/CLI workflow still
works identically — since none of the underlying AWS resources change, only the editor surface does. The
main friction in practice is muscle memory, not technical capability: a team used to Cloud9's fully
browser-hosted environment (useful for onboarding a contractor with no local setup at all, for instance)
loses that specific convenience and needs a different answer for it, typically a pre-configured local dev
container or a documented local setup script instead.

## Cloud9 — Status and Why It's Not the Answer for a New Project

**Cloud9**, AWS's cloud-based IDE, **stopped onboarding new customers in July 2024** — existing Cloud9
environments keep working and keep receiving security patches, but AWS is not investing in new Cloud9
features and directs new customers toward the AWS Toolkit IDE extensions for VS Code/JetBrains, alongside
CloudShell for terminal-only needs. Any content still describing Cloud9 as the current recommended cloud
IDE for a new AWS project is out of date — worth knowing specifically because it's exactly the kind of
stale-training-data trap this series' research-discipline policy exists to catch.

## AWS Toolkit IDE Extensions — The Real Cloud9 Replacement

Rather than a single cloud-hosted IDE product, AWS's current developer-environment strategy is **local IDE
extensions** — the AWS Toolkit for VS Code and the AWS Toolkit for JetBrains IDEs — bringing AWS-specific
capability into whichever editor a developer already uses, rather than asking them to switch editors
entirely. Concretely, this covers: browsing and invoking deployed Lambda functions and viewing their
CloudWatch Logs without leaving the editor, a built-in SAM template schema with autocomplete, one-click
`sam local` debugging with real breakpoints inside the local Docker-emulated runtime, and CodeCatalyst
integration for the projects using it. **Amazon Q Developer** (the successor to CodeWhisperer, and to
CodeGuru Reviewer's code-review role above) ships as part of the same toolkit — inline code suggestions,
chat-based debugging assistance, and the automated code-review capability that replaced CodeGuru Reviewer
for new repositories, all inside the same local editor rather than a separate cloud-hosted surface.

## A Full Worked Example: Shipping the Order-Status API Safely

Extending Part 13's order-status API with a real deployment pipeline:

1. The Lambda function backing `GET /orders/{id}` is defined in a SAM template, developed and smoke-tested
   locally with `sam local start-api` before ever touching a shared AWS account.
2. `sam build` and `sam deploy` run inside a CodeBuild stage (Part 11), which itself pulls its own
   dependencies through a CodeArtifact repository proxying PyPI, so a public-registry outage can't block a
   production deploy.
3. The SAM template's `AutoPublishAlias: prod` property (SAM's shorthand for the version/alias mechanism
   above) is configured with `DeploymentPreference: Canary10Percent5Minutes`, wired to a CloudWatch alarm
   on the function's error rate.
4. A bad deploy trips the alarm within the first five minutes at 10% traffic; CodeDeploy automatically
   shifts the alias back to the previous version — the customer-facing blast radius is capped at roughly
   10% of requests for five minutes, not a full outage.
5. The frontend engineer testing the new route locally never needed a Cloud9 environment or a shared dev
   account at all — `sam local start-api` plus CloudShell for the occasional one-off AWS CLI check covered
   the entire loop.
6. The function itself pulls its payment-provider API key from Secrets Manager at cold start via the
   Secrets Manager Lambda extension, never as a plain environment variable — so the credential never
   appears in the SAM template, the CloudFormation stack's parameters, or the function's visible
   configuration in the console.
7. The function's IAM execution role is generated automatically by a SAM policy template
   (`DynamoDBReadPolicy`, scoped to the exact order-status table) rather than hand-written — reviewing the
   template's `Policies` block during code review is enough to confirm least privilege, with no separate
   IAM policy document to audit.
8. `sam pipeline bootstrap` originally generated the three-stage (test/staging/production) CodePipeline
   this whole flow runs through, with per-stage IAM roles already scoped correctly — the platform team
   never hand-wrote that cross-account pipeline wiring for this specific application.

## Cost Considerations for Developer Tooling

Most of this part's tools carry no direct charge beyond the resources they manage: SAM, CodeDeploy's
Lambda traffic-shifting, and CloudShell are all free — the bill is exactly the underlying Lambda/API
Gateway/EC2 usage, the same "no markup" property already noted for Beanstalk itself. CodeArtifact bills
for storage and data transfer (genuinely cheap at typical package-repository scale, but worth watching if
an organization vendors very large binary artifacts through it rather than typical language packages), and
Amazon Q Developer's advanced features sit behind a paid tier beyond its free individual usage limits, and
CloudShell itself has no per-session charge at all, only the ordinary cost of whatever AWS API calls a
session happens to make. Part 16 covers cost-optimization tooling (Cost Explorer, Budgets, Compute
Optimizer) in full — the
practical takeaway here is narrower: choosing SAM/CDK/CodeDeploy over a competing third-party tool is very
rarely a cost decision on its own, since AWS's own developer tooling layer is priced to not be the
expensive part of the equation.

## Developer Tooling Best Practices — The Consolidated Checklist

- Don't hand-edit resources Elastic Beanstalk manages directly — customize through `.ebextensions`/
  `.platform` so changes survive the next environment update.
- Prefer Beanstalk's swap-URL blue/green pattern over in-place deployment policies whenever an instant,
  unambiguous rollback matters more than deployment cost.
- Reach for SAM specifically for the `sam local` testing loop; plain CDK is equally valid when a project's
  infrastructure spans well beyond serverless resources.
- Never invoke a Lambda function by its raw version ARN from a caller — always the alias, so traffic
  shifting works without touching every caller's configuration.
- Never ship a canary/linear Lambda or API Gateway deployment without an attached CloudWatch alarm — the
  gradual shift alone only delays a bad deploy's full impact, it doesn't prevent it.
- Route new source control to GitHub/GitLab/Bitbucket, not CodeCommit, for any new project started today.
- Route new automated code review to Amazon Q Developer / Amazon Inspector, not CodeGuru Reviewer, for any
  new repository.
- Use CloudShell for quick one-off CLI tasks; don't try to force it into being a persistent dev environment.
- Fetch secrets at runtime through Secrets Manager/Parameter Store, never as a plain deployment-time
  environment variable — an environment variable is a materially weaker, unaudited boundary.
- Test at all three layers (unit, `sam local`, a real deployed stage) — local emulation alone never
  enforces real IAM permissions, so an over-narrow policy only surfaces once genuinely deployed.

## Part 14 CLI Cheat Sheet

| Task | Command |
|---|---|
| Create a Beanstalk application | `eb init` |
| Deploy the current directory | `eb deploy` |
| Swap two environment URLs | `aws elasticbeanstalk swap-environment-cnames --source-environment-name <a> --destination-environment-name <b>` |
| Build a SAM application | `sam build` |
| Invoke a function locally | `sam local invoke OrderStatusFunction -e event.json` |
| Deploy a SAM application | `sam deploy --guided` |
| Publish a new Lambda version | `aws lambda publish-version --function-name <name>` |
| Update an alias's routing config | `aws lambda update-alias --function-name <name> --name prod --routing-config AdditionalVersionWeights={"13"=0.1}` |
| Create a CodeDeploy deployment for Lambda | `aws deploy create-deployment --application-name <app> --deployment-group-name <group> --revision <revision>` |
| List CodeArtifact repositories | `aws codeartifact list-repositories --domain <domain>` |
| Log into CodeArtifact for npm | `aws codeartifact login --tool npm --repository <repo> --domain <domain>` |

## Common Mistakes and Interview Traps

| Mistake | Why it's wrong | Correct approach |
|---|---|---|
| Hand-modifying an ASG that Beanstalk manages | Beanstalk's own reconciliation silently reverts the change on the next environment update | Customize through `.ebextensions`/`.platform` instead |
| Calling a Lambda function by a specific version ARN in production code | Bypasses the alias indirection entirely — traffic shifting becomes impossible without redeploying every caller | Always invoke through the alias |
| Shipping a canary deployment with no CloudWatch alarm attached | Only delays full exposure to a bad deploy by a few minutes, doesn't prevent it | Always pair gradual shifts with an error-rate/latency alarm and automatic rollback |
| Starting a brand-new project on CodeCommit or Cloud9 | Both stopped onboarding new customers years ago and aren't receiving new features | Use a third-party Git host and CloudShell/AWS Toolkit instead |
| Assuming CodeGuru Reviewer is still the current code-review recommendation | It moved to maintenance mode in November 2025 | Point new repositories at Amazon Q Developer instead |
| Storing a database credential as a Beanstalk environment property or Lambda plain environment variable | Both are visible to anyone with read access to the resource's configuration, with no access audit trail | Fetch it at runtime from Secrets Manager/Parameter Store instead |
| Treating SAM as a completely separate deployment mechanism from CloudFormation | SAM templates transform into and deploy as ordinary CloudFormation stacks | Apply the same stack/change-set/drift-detection knowledge from Part 11 |

## Worked Practice Problems

**Problem 1:** A team's Elastic Beanstalk-hosted API needs a zero-downtime deployment with an instant,
guaranteed rollback path if the new version has a critical bug discovered minutes after going live. Which
deployment policy fits, and why not "Immutable"?

*Answer:* Blue/Green via swap-environment-URLs. Immutable does avoid downtime and is reasonably fast to
roll back, but its rollback still means re-triggering a deployment action; a URL swap is a single API call
that instantly exchanges traffic back to the fully intact previous environment, with no new deployment
required at all — the fastest possible rollback path Beanstalk offers.

**Problem 2:** A serverless application's CI pipeline currently runs `aws cloudformation deploy` directly
against a hand-written template defining several `AWS::Lambda::Function` and `AWS::ApiGateway::*`
resources. The team wants faster local iteration without abandoning CloudFormation. What's the smallest
change that gets them there?

*Answer:* Migrate the template to SAM syntax (`AWS::Serverless::Function`/`AWS::Serverless::Api`, adding
the `Transform` header) and adopt the SAM CLI for local development (`sam local start-api`,
`sam local invoke`). The deploy target doesn't change — it's still CloudFormation underneath — so this is
a tooling and template-syntax change, not an architectural rewrite, and it's specifically the local-testing
gap plain CloudFormation never closes.

**Problem 3:** A public API's Lambda backend is deployed with `Canary10Percent5Minutes`, and five minutes
after a rollout the function's error-rate alarm trips. What happens automatically, and what should the
on-call engineer NOT need to do manually?

*Answer:* CodeDeploy automatically shifts the alias's traffic weighting back to the previous, known-good
version — the on-call engineer should not need to manually edit the alias's routing configuration or
redeploy anything to restore service; their actual job at that point is investigating why the new version
failed, not performing the rollback itself.

**Problem 4:** A team wants a synthetic smoke test to run automatically against a brand-new Lambda version
before it receives any real customer traffic at all, not just a reduced percentage. What CodeDeploy feature
provides this, and how is it different from a canary?

*Answer:* A `PreTraffic` validation hook. A canary still exposes some percentage of real traffic to the new
version during its shift window; a `PreTraffic` hook runs entirely before any traffic-shifting begins, so a
failure there blocks the deployment from ever receiving live requests at all — a strictly stronger
guarantee for catching an obviously broken deployment, though it doesn't replace a canary's value for
catching subtler issues that only manifest under real, varied traffic.

## Summary and What's Next

Elastic Beanstalk automates the same EC2/ASG/ALB primitives from Parts 3/4/8 into one managed unit, best
suited to teams wanting less setup than a hand-built ASG without moving to containers or serverless
entirely. SAM does the equivalent for Part 7's serverless resources, adding a genuinely valuable local
testing loop on top of the same CloudFormation deployment target Part 11 already covers. Lambda's
version/alias mechanism, paired with CodeDeploy's canary/linear shifting and an attached CloudWatch alarm,
is what turns "deploy" into "deploy safely" — the same blast-radius-limiting instinct behind every
deployment strategy this series has covered, applied at the function level. And two currency corrections
worth carrying forward: CodeCommit and Cloud9 are both closed to new customers, with GitHub/GitLab/AWS
Toolkit and CodeGuru Reviewer's successor, Amazon Q Developer, as the tools a new project should actually
reach for today. None of this is a competing philosophy to Part 11's pipeline material — CodeArtifact,
SAM, and CodeDeploy's traffic shifting all plug directly into the same CodeBuild/CodePipeline foundation
already established there.

**Part 15** moves from shipping code to operating the fleet it runs on: Systems Manager's Session Manager,
Run Command, Patch Manager, and Automation documents — the operational tooling SOA-C02 weights most
heavily, and the direct answer to "how does an SRE actually manage hundreds of EC2 instances without SSH
keys scattered everywhere."
