Part 14 of 1936 min read · 3 diagramsAI-assisted

Elastic Beanstalk, SAM & Developer Tooling

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
  2. Elastic Beanstalk — Managed PaaS, Positioned Against Everything Else in This Series
  3. What Elastic Beanstalk Actually Provisions
  4. Supported Platforms and the "Just Upload Code" Model
  5. Environment Tiers: Web Server vs Worker
  6. Worker Tier, Worked: Periodic Tasks Without a Separate Scheduler
  7. Elastic Beanstalk Deployment Policies
  8. .ebextensions and .platform — Customizing the Managed Environment
  9. Elastic Beanstalk Environment Types and Swap URLs
  10. Elastic Beanstalk Health Monitoring and Managed Platform Updates
  11. Cost Shape: Beanstalk Adds No Markup
  12. Saved Configurations — Reproducing an Environment Deliberately
  13. A Currency Note: Multi-Container Docker Platforms
  14. When Elastic Beanstalk Fits, and When It Doesn't
  15. Elastic Beanstalk vs App Runner — Two Managed Options, Different Generations
  16. Debugging a Failed Elastic Beanstalk Deployment
  17. AWS SAM — Serverless Application Model, Core Concepts
  18. The SAM Template — CloudFormation With Serverless Shortcuts
  19. What sam build/sam deploy Actually Do Under the Hood
  20. The SAM CLI Development Loop
  21. Testing Strategy: Unit, Local Integration, and Cloud Integration
  22. SAM vs Plain CloudFormation vs CDK — Choosing
  23. SAM Accelerate and Policy Templates
  24. SAM Nested Applications and the Serverless Application Repository
  25. sam pipeline — Bootstrapping CI/CD for a SAM Application
  26. Lambda Deployment Safety: Versions, Aliases, and Weighted Routing
  27. CodeDeploy for Lambda: Canary and Linear Traffic Shifting
  28. Automated Rollback on CloudWatch Alarm
  29. CodeDeploy for API Gateway Too
  30. Pre-Traffic and Post-Traffic Validation Hooks
  31. Choosing a Compute and Deployment Combination
  32. Least-Privilege Roles for the Deployment Tooling Itself
  33. CodeArtifact — A Managed Package Repository
  34. CodeArtifact Upstream Repositories and Approved-Package Workflows
  35. CodeArtifact Domains — Sharing Repositories Across an Organization
  36. Source Control in 2026: Where CodeCommit Actually Stands
  37. CodeGuru: What's Still Active, and What Moved to Amazon Q Developer
  38. Managing Sensitive Data in Application Code
  39. AWS CloudShell — The Practical In-Browser Terminal
  40. Migrating Off an Existing Cloud9 Environment
  41. Cloud9 — Status and Why It's Not the Answer for a New Project
  42. AWS Toolkit IDE Extensions — The Real Cloud9 Replacement
  43. A Full Worked Example: Shipping the Order-Status API Safely
  44. Cost Considerations for Developer Tooling
  45. Developer Tooling Best Practices — The Consolidated Checklist
  46. Part 14 CLI Cheat Sheet
  47. Common Mistakes and Interview Traps
  48. Worked Practice Problems
  49. Summary and What's 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.

Diagram

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#

PolicyHow it worksDowntimeRollback speed
All at onceEvery instance updated simultaneouslyBrief outage during deployRequires a new deploy
RollingUpdates a configurable batch of instances at a time, in placeNone, but reduced capacity during rolloutRequires a new deploy
Rolling with additional batchLaunches a new batch first, then rolls in the same patternNone, capacity maintained throughoutRequires a new deploy
ImmutableLaunches an entirely new, parallel ASG; only cuts over once healthyNoneFast — old ASG still exists briefly
Blue/Green (swap)Deploys to a completely separate environment, then swaps the CNAMENoneInstant — 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#

SignalFavors
A team wants EC2-level control (custom AMI tweaks, SSH access) with less setup burden than hand-building an ASGElastic 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 invocationLambda (Part 7)
The team needs fine-grained infrastructure-as-code control beyond what a PaaS abstraction exposesHand-built EC2/ECS via CloudFormation/CDK (Part 11)
A small team wants to deploy an existing monolithic web app with minimal new tooling to learnElastic 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 BeanstalkApp Runner
Underlying computeEC2 instances, visible and inspectableFully abstracted — no visible EC2/ASG at all
InputSource bundle (ZIP/WAR) or container imageContainer image, or source code built by App Runner itself
Scale-to-zeroNo — an ASG's minimum capacity always runsYes — genuinely scales down when idle
Networking customizationFull VPC/security-group controlMore limited, VPC connector required for private resources
Best fitExisting EC2-shaped applications, teams wanting inspectable infrastructureNew 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#

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#

Diagram

The SAM CLI Development Loop#

CommandWhat it does
sam initScaffolds a new project from a starter template
sam buildResolves dependencies and packages each function into .aws-sam/build/, ready for local testing or deploy
sam local invokeRuns one function locally, in a Docker container matching the real Lambda runtime, without deploying anything
sam local start-apiSpins up a local API Gateway emulator, routing to local function invocations — the fast local dev loop for an API-backed function
sam deploy --guidedPackages artifacts to S3, then deploys the underlying CloudFormation stack, prompting for parameters the first time
sam logsTails 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:

LayerToolCatches
UnitA normal test framework (pytest, Jest) with mocked AWS SDK callsBusiness logic bugs, independent of any AWS behavior
Local integrationsam local invoke/start-api against a real Docker-emulated Lambda runtimeRuntime-version mismatches, missing dependencies, cold-start-shaped bugs
Cloud integrationA deployed test/staging stage (often via sam sync for fast iteration), hitting real AWS servicesIAM 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 CloudFormationSAMCDK
LanguageYAML/JSON onlyYAML/JSON, with serverless shortcutsReal programming language (TypeScript, Python, Java, ...)
Best fitAny AWS resource, maximum explicitnessServerless-heavy applications, local Lambda testingComplex logic, reusable constructs, non-serverless infra too
Local testingNone built insam localNone built in (synthesizes to CloudFormation, same as plain)
Under the hoodItselfTransforms to CloudFormationSynthesizes 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:

Diagram
ConfigurationShape
AllAtOnce100% immediately — fastest, no gradual safety net
Canary10Percent5Minutes10% 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 choiceDeployment mechanismFits
EC2 (hand-built ASG)CodeDeploy in-place or blue/green (Part 11)Maximum control, existing non-containerized workloads
Elastic BeanstalkBeanstalk deployment policies, swap-URL blue/greenLess setup than hand-built EC2, still EC2-based
ECS/FargateECS rolling or blue/green via CodeDeploy (Part 7)Containerized services wanting orchestration
LambdaAlias weighting via CodeDeploy canary/linearEvent-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#

TaskCommand
Create a Beanstalk applicationeb init
Deploy the current directoryeb deploy
Swap two environment URLsaws elasticbeanstalk swap-environment-cnames --source-environment-name <a> --destination-environment-name <b>
Build a SAM applicationsam build
Invoke a function locallysam local invoke OrderStatusFunction -e event.json
Deploy a SAM applicationsam deploy --guided
Publish a new Lambda versionaws lambda publish-version --function-name <name>
Update an alias's routing configaws lambda update-alias --function-name <name> --name prod --routing-config AdditionalVersionWeights={"13"=0.1}
Create a CodeDeploy deployment for Lambdaaws deploy create-deployment --application-name <app> --deployment-group-name <group> --revision <revision>
List CodeArtifact repositoriesaws codeartifact list-repositories --domain <domain>
Log into CodeArtifact for npmaws codeartifact login --tool npm --repository <repo> --domain <domain>

Common Mistakes and Interview Traps#

MistakeWhy it's wrongCorrect approach
Hand-modifying an ASG that Beanstalk managesBeanstalk's own reconciliation silently reverts the change on the next environment updateCustomize through .ebextensions/.platform instead
Calling a Lambda function by a specific version ARN in production codeBypasses the alias indirection entirely — traffic shifting becomes impossible without redeploying every callerAlways invoke through the alias
Shipping a canary deployment with no CloudWatch alarm attachedOnly delays full exposure to a bad deploy by a few minutes, doesn't prevent itAlways pair gradual shifts with an error-rate/latency alarm and automatic rollback
Starting a brand-new project on CodeCommit or Cloud9Both stopped onboarding new customers years ago and aren't receiving new featuresUse a third-party Git host and CloudShell/AWS Toolkit instead
Assuming CodeGuru Reviewer is still the current code-review recommendationIt moved to maintenance mode in November 2025Point new repositories at Amazon Q Developer instead
Storing a database credential as a Beanstalk environment property or Lambda plain environment variableBoth are visible to anyone with read access to the resource's configuration, with no access audit trailFetch it at runtime from Secrets Manager/Parameter Store instead
Treating SAM as a completely separate deployment mechanism from CloudFormationSAM templates transform into and deploy as ordinary CloudFormation stacksApply 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."