A Platform-as-a-Service (PaaS) orchestration layer: you upload application code, Elastic Beanstalk provisions and manages the underlying EC2 instances, Auto Scaling group, load balancer, security groups, and CloudWatch monitoring — while still handing you full access to the underlying resources if you need it. This module pairs "how it actually works" understanding with the exam-reasoning layer DVA-C02 tests, especially around deployment options and where Beanstalk sits relative to ECS/Fargate and Lambda.
A logical container for your deployable code — versions, environments, and configurations all belong to one application. Think of it as the top-level project folder in the Elastic Beanstalk console.
A specific, labeled, deployable iteration of your code (a ZIP/WAR file, or a Dockerrun.aws.json for Docker platforms), stored in an Elastic Beanstalk-managed S3 bucket. You deploy application versions into environments — this is what makes rollback possible (redeploy an older version).
A running collection of AWS resources (EC2/ASG/ELB/security groups/etc.) executing one application version at a time. You typically run multiple environments per application (e.g. myapp-dev, myapp-staging, myapp-prod), each with its own configuration and URL/CNAME.
The full set of parameters describing an environment — instance type, deployment policy, Auto Scaling min/max, environment variables, VPC/subnets, health reporting level, etc. Can be captured as a reusable "saved configuration" and applied to new environments.
The managed runtime + OS + web/app server + language dependencies stack Beanstalk provisions on your instances (e.g. Node.js on Amazon Linux 2023, Python, Java (Corretto/Tomcat), .NET on Windows Server, Docker, Go, Ruby, PHP). AWS maintains "platform versions" you can upgrade to; you can also build a fully custom platform with Packer if none of the managed ones fit.
Chosen at environment creation: Web server tier (fronted by a load balancer, serves HTTP requests) or Worker tier (no load balancer; polls an Amazon SQS queue and processes messages in the background). Cannot be changed after creation without recreating the environment.
Developer packages source code as a ZIP/WAR (or a Dockerrun.aws.json for Docker), optionally including an .ebextensions/.platform folder with configuration files
Console upload, EB CLI (eb deploy), or a CI/CD pipeline (e.g. CodePipeline) uploads the bundle — Elastic Beanstalk stores it as a new Application Version in its managed S3 bucket
Elastic Beanstalk generates/updates an AWS CloudFormation stack that provisions or updates EC2 instances, the Auto Scaling group, the load balancer, security groups, and CloudWatch alarms to match the environment configuration
The chosen policy — All at once / Rolling / Rolling with additional batch / Immutable / Traffic Splitting — governs exactly how the new application version replaces the old one across the fleet
The Basic or Enhanced health agent on each instance reports application and instance status back to the Elastic Beanstalk health dashboard and to CloudWatch
Requests reach the environment via its Beanstalk-assigned CNAME (or a custom domain mapped through Route 53). For blue/green releases, a second environment is built, tested independently, then cut over via an environment swap (CNAME swap)
Nearly every Elastic Beanstalk question tests one of three things: (1) can you pick the right deployment policy for a described downtime/cost/rollback requirement, (2) do you know Beanstalk is PaaS with retained infrastructure access — the deciding factor against Lambda (no server access) and a lighter-weight alternative to self-managing ECS/Fargate, or (3) can you spot the operational traps: .ebextensions secrets in source control, RDS coupled to an environment, or environment-variable changes triggering a redeploy.
| DVA-C02 Domain | Where Elastic Beanstalk Shows Up |
|---|---|
| Domain 1 — Development with AWS Services | Packaging application versions, using the EB CLI, structuring .ebextensions/.platform config, worker tier + SQS integration |
| Domain 2 — Security | Instance profile vs service role, environment variables vs Secrets Manager/SSM Parameter Store for credentials, VPC placement |
| Domain 3 — Deployment | The centerpiece domain for this service — deployment policy selection, blue/green via environment swap, CI/CD integration with CodePipeline/CodeBuild/CodeDeploy |
| Domain 4 — Troubleshooting & Optimization | Reading the health dashboard, Basic vs Enhanced health reporting, diagnosing a failed deployment, log retrieval (bundle logs / instance logs) |
Exact weightings shift slightly between guide revisions, but deployment strategy questions (Domain 3) are the single most reliable place Elastic Beanstalk appears on DVA-C02.
.ebextensions mechanics: option_settings, Resources, packages, container_commands, leader_onlyExam appearance probability: HIGH
Related guides: 01 — Containers (ECS/ECR/Fargate/EKS) · 02 — CI/CD Pipeline services · 08 — Cross-Service Architectures
The settings and mechanics that most commonly appear inside DVA-C02 scenario questions — deployment options in full, health monitoring, .ebextensions, and environment variables.
myapp-green) running the new version; test it independently via its own environment URL; then swap the CNAMEs of the two environmentsSwap Environment URLs — a console action/CLI command entirely separate from the deployment-policy dropdown.cron.yaml file in the application bundle lets the worker tier run scheduled (cron-like) jobsEnvironment health colors (see the scale at the top of the Overview tab): Green = passing, Yellow = one or more warnings (e.g. elevated latency, some instances degraded), Red = severe (majority of instances failing or application errors), Grey = insufficient data, environment is updating, or processes are suspended.
.ebextensions.ebextensions IsA folder named .ebextensions at the root of your application source bundle, containing one or more YAML or JSON files (extension .config). Elastic Beanstalk applies these automatically during environment provisioning and every subsequent deployment — this is the primary, version-controlled way to customize the environment beyond what the console exposes.
.ebextensions/01_environment.config
─────────────────────────────────────
option_settings:
aws:elasticbeanstalk:application:environment:
NODE_ENV: production
aws:autoscaling:asg:
MinSize: 2
MaxSize: 6
Resources:
AWSEBCloudwatchAlarmHigh:
Type: AWS::CloudWatch::Alarm
Properties:
MetricName: CPUUtilization
Namespace: AWS/EC2
Threshold: 80
ComparisonOperator: GreaterThanThreshold
packages:
yum:
git: []
container_commands:
01_migrate:
command: "python manage.py migrate"
leader_only: true
option_settings — sets configuration values equivalent to what you'd set in the console (environment variables, Auto Scaling min/max, instance type, etc.).Resources — lets you define or override additional native CloudFormation resources (e.g. custom CloudWatch alarms) as part of the same stack Beanstalk manages, without needing a separate CloudFormation deployment.packages / commands / container_commands / files — install OS packages, run shell commands before (commands) or after (container_commands) the application/container is set up, or place files on the instance.leader_only: the "leader" instance is elected exactly once, at environment creation. A container_commands entry with leader_only: true (commonly used for one-time DB migrations) will NOT re-run on instances added later by Auto Scaling or by a new deployment's rolling/immutable process — it only ever ran on the original leader. Don't rely on it for logic that must execute on every new instance..ebextensions option_settings under aws:elasticbeanstalk:application:environment, or a saved configurationprocess.env.X in Node.js, os.environ['X'] in Python, System.getenv("X") in Java.ebextensions files are typically committed to source control (they travel with your application bundle). Hardcoding a database password or API key directly as plaintext in an option_settings block is a common wrong-answer pattern the exam tests for.SecureString), then have the application retrieve it at runtime using its ARN/name (which itself is safe to store as a plain environment variable, since it's just a pointer, not the secret).Requirement → Keywords → Expected Answer → why every distractor fails. Written in the "A company needs to...", "What is the MOST appropriate solution?" style DVA-C02 actually uses.
AWS Elastic Beanstalk
| Distractor | Why it's wrong |
|---|---|
AWS Lambda | No server to SSH into at all — fully abstracted compute, and a poor fit for a long-running monolith |
Self-managed EC2 + Auto Scaling | Full SSH control, but the team must build the ASG/ELB/deployment tooling themselves — violates "least operational overhead" |
Amazon ECS on EC2 (self-managed) | Requires containerizing the app plus managing the cluster — more upfront work than Beanstalk for a straightforward monolith |
Rolling with additional batch deployment policy
| Distractor | Why it's wrong |
|---|---|
| Rolling | Reduces total fleet capacity while each batch is out of service — fails the "never drop below 100%" requirement |
| Immutable | Also maintains full capacity, but doubles the entire fleet for the whole deployment rather than adding a single extra batch — more cost/complexity than the requirement calls for |
| All at once | Causes a full outage — the opposite of maintaining capacity |
Immutable deployment policy
| Distractor | Why it's wrong |
|---|---|
| Rolling with additional batch | Cheaper, but rollback requires a brand-new deployment of the old version — not the fastest option, and some instances briefly ran the bad code |
| Blue/Green environment swap | Also very fast to roll back, but requires creating and managing a whole second Elastic Beanstalk environment — the scenario specifically calls for staying within one environment |
| All at once | No parallel fleet at all — if the new version fails, every instance is already broken with no immediate healthy fallback |
Create a second environment, test it independently, then perform an Environment Swap (CNAME swap)
| Distractor | Why it's wrong |
|---|---|
| Traffic Splitting (canary) | Exposes a percentage of REAL production traffic to the new version immediately — the requirement explicitly wants zero live exposure until cutover |
| Immutable | New instances run inside the SAME environment/URL as production — there's no separate URL to fully validate against before cutover |
| Rolling | No isolation at all — the new version starts serving live traffic as soon as the first batch updates |
Traffic Splitting (canary) deployment policy with an Application Load Balancer
| Distractor | Why it's wrong |
|---|---|
| Blue/Green environment swap | An instant, all-or-nothing cutover — not a gradual real-traffic ramp |
| Rolling with additional batch | Shifts traffic by replacing whole batches of instances, not by weighted percentage routing, and has no built-in automatic rollback on error-rate thresholds |
| Immutable | New fleet only receives traffic after full cutover, not a gradually increasing percentage |
Elastic Beanstalk Worker environment tier (backed by Amazon SQS)
| Distractor | Why it's wrong |
|---|---|
| Web server tier with a custom cron/polling script | Works, but the team has to build and maintain the polling daemon themselves — Worker tier does this natively |
| Amazon EC2 with a custom daemon | Even more undifferentiated heavy lifting than the Beanstalk answer |
| Amazon S3 event notification directly to the app | S3 events don't apply here — the requirement is queue-driven background processing, not object-upload triggers |
An .ebextensions configuration file (packages + Resources sections)
| Distractor | Why it's wrong |
|---|---|
| Build a custom AMI | Works but is heavier operational overhead and explicitly excluded by the requirement |
| Manually SSH into each instance and install packages | Not automated, not repeatable, and lost the moment Auto Scaling launches a new instance |
| A user data script only | Can install packages, but doesn't natively integrate with Elastic Beanstalk's own CloudFormation stack the way .ebextensions Resources does for creating the alarm |
Store the credential in AWS Secrets Manager (or SSM Parameter Store as a SecureString) and have the application retrieve it at runtime by ARN/name
| Distractor | Why it's wrong |
|---|---|
Hardcode the password in an .ebextensions option_settings block | Exactly the plaintext-in-source-control problem the requirement forbids |
| Hardcode the password directly in application code | Same problem, arguably worse — no rotation, no access control on the secret itself |
| Store it only as a console-set environment variable with no secret manager | Better than source control, but still fully visible in plaintext to anyone with read access to the environment configuration — not a true secret store with rotation/audit |
Enable Enhanced Health Reporting
| Distractor | Why it's wrong |
|---|---|
| Basic health reporting | Only reports pass/fail instance and ELB status — no HTTP status code or latency visibility |
| AWS X-Ray | Provides distributed tracing/latency analysis, but isn't Elastic Beanstalk's own environment health mechanism and doesn't drive the health dashboard or health-based Auto Scaling |
| CloudWatch alarms on default EC2 metrics alone | Default EC2 metrics (CPU, network) don't include HTTP status code histograms — Enhanced health reporting is what surfaces those application-level signals |
.ebextensionsbuildspec.ymlSee 02 — CI/CD Pipeline Services for the full pipeline mechanics.
A team runs a Java web application on Elastic Beanstalk (Web server tier, load balanced/auto scaling, Enhanced health reporting) with its database decoupled as a standalone Amazon RDS instance. Developers push to their source repository, which triggers the following flow:
.ebextensions folder.myapp-staging Elastic Beanstalk environment using the All at once policy (acceptable here since staging tolerates brief downtime), where automated smoke tests run against its dedicated URL.myapp-green production-configuration environment. Once its health dashboard reports Green and manual/automated checks pass, the pipeline performs an Environment Swap (CNAME swap) with the live myapp-blue environment — instant cutover, zero downtime.myapp-blue immediately since it was never decommissioned.myapp-blue environment is terminated (or kept warm as the next rollback target for the following release), while the RDS instance — decoupled from both environments — is untouched throughout.This pattern gives the team the deployment safety of Blue/Green with the automation of a full CI/CD pipeline, and keeps the database's lifecycle independent of any single environment's churn. See also 08 — Cross-Service Architectures for the "Enterprise application deployment" pattern that builds on this.
.ebextensions| Dimension | Elastic Beanstalk | ECS / Fargate | Lambda |
|---|---|---|---|
| Operational overhead | Low — AWS provisions/manages EC2, ASG, ELB for you | Medium — you design task definitions, cluster/service topology (or use Fargate to drop server management) | Lowest — no servers, no cluster, no OS patching at all |
| Underlying infra access | Full — SSH into instances, inspect security groups/CloudFormation stack directly | Partial (EC2 launch type) to none (Fargate) — container-level access only, no host SSH on Fargate | None — fully abstracted, no server concept |
| Scaling model | EC2 Auto Scaling group, instance-level | Service-level task scaling (target tracking), Fargate scales tasks not servers | Automatic, per-request concurrency scaling |
| Deployment granularity | Whole environment (all instances behind one ELB) | Per service/task definition — supports many independently-deployed microservices per cluster | Per function — independently versioned/deployed |
| Best for | Traditional web apps/APIs needing infra control with minimal setup effort | Containerized microservices needing orchestration control and portability | Event-driven, short-duration, spiky or infrequent workloads |
| Typical exam cue | "least operational overhead but still need SSH/infrastructure control" | "containerized microservices," "need orchestration control," "portable across environments" | "event-driven," "pay only when code runs," "no servers to manage at all" |
| Misconception | Reality |
|---|---|
| "Elastic Beanstalk is serverless" | It provisions real EC2 instances, an ASG, and an ELB that you're billed for. Beanstalk itself has no service fee, but the underlying resources are ordinary, metered AWS resources |
| "Blue/Green is one of the deployment policy options in the environment configuration" | It is not. The deployment-policy dropdown only offers All at once / Rolling / Rolling with additional batch / Immutable / Traffic Splitting. Blue/Green is a separate workflow: create a second environment, then perform an Environment Swap |
| "Immutable deployments are free" | They temporarily double compute cost — a full parallel fleet runs until cutover |
| "All at once is safe enough for production because it's the default-sounding option" | It causes a full outage with no fallback if the new version fails — appropriate for dev/test only |
| "Terminating an environment never affects the database" | True only if RDS was decoupled (created outside the environment). An RDS instance created inside the environment is terminated along with it by default |
| "You can't customize the underlying EC2 instances in Elastic Beanstalk" | You can — via .ebextensions, direct console changes, or SSH. This retained access is the core reason Beanstalk beats Lambda for scenarios needing infrastructure control |
| "Changing an environment variable applies instantly with zero disruption" | It's a configuration change like any other — it triggers a new deployment/instance update following the environment's configured deployment policy |
"leader_only: true means the command runs once per deployment on some instance" | The leader is elected once, at environment creation only. New instances added later by scaling or subsequent deployments do NOT re-run leader_only commands |
Three self-contained exercises using the real EB CLI (and aws elasticbeanstalk) against eu-west-1. They turn the deployment-policy and .ebextensions theory from the other tabs into something you actually watch happen — a broken deploy under the default policy, the same break survived under Immutable, and a config file that installs a package and sets an environment variable for real. Bring your own tiny app (any of the EB-supported platforms works; examples below assume Node.js) and remember to eb terminate the environment when you're done so it doesn't keep billing.
eb --version eb init my-eb-lab-app --platform node.js --region eu-west-1A local
.elasticbeanstalk/config.yml is created, pinned to the eu-west-1 region and the Node.js platform.
eb create eb-lab-env --region eu-west-1 --instance-type t3.microAfter several minutes, the environment reports health Green in both the CLI output and the console health dashboard.
eb status eb health eb-lab-envCLI shows
Health: Green, causes list is empty, and per-instance status is all "Ok" — matches what the console Health tab renders visually.
# edit app.js so the server throws on boot, e.g.:
# throw new Error("simulated startup failure");
eb deploy eb-lab-env
The deploy reports failure; the health dashboard flips to Red/Severe across essentially the whole fleet at once, because All at once pushed the bad build to every instance simultaneously with no healthy fallback capacity.
eb events eb-lab-env --follow eb logs eb-lab-envEvents show the failed deployment and degraded/severe health transition; the retrieved logs contain the simulated startup error on every instance.
This is the exact mechanic behind every "All at once causes a full outage" exam line — you've now watched it happen instead of just memorizing it. Notice there was no partially-healthy fallback fleet to route around the bad build; that absence is precisely what the next exercise fixes.
# revert the breaking change in app.js, then: eb deploy eb-lab-envHealth returns to Green — you're back to a clean baseline before introducing a second variable.
.ebextensions config file that switches the environment's deployment policy to Immutable.
mkdir .ebextensions
cat > .ebextensions/01_deployment_policy.config <<'EOF'
option_settings:
aws:elasticbeanstalk:command:
DeploymentPolicy: Immutable
EOF
eb deploy eb-lab-env
The deploy succeeds and applies the configuration change; eb config eb-lab-env now shows DeploymentPolicy: Immutable instead of the default.
# reapply the same "throw on boot" change to app.js eb deploy eb-lab-envThe deploy fails, but the environment health dashboard stays Green throughout — Beanstalk launched a brand-new temporary Auto Scaling group running the bad build, watched it fail health checks, and terminated it automatically without ever routing production traffic to it. The original fleet kept serving the last good version the entire time.
eb events eb-lab-env --followEvents show a new temporary environment/ASG being created, instances failing health checks, and an automatic rollback/termination of the temporary fleet — with no "environment health: Severe" event for the live environment itself.
# revert app.js again, then: eb deploy eb-lab-envHealth is Green again, this time still running under the Immutable policy.
Same bug, same code, two completely different production outcomes — that's the risk/speed/cost tradeoff DVA-C02 tests repeatedly. All at once was fastest to deploy but broke every instance at once; Immutable was slower to deploy (a full new fleet had to boot and pass health checks) but the bad build never touched live traffic. Also note the mechanism: it's a temporary ASG inside the same environment/CNAME, not a second environment — don't confuse this with Blue/Green.
.ebextensions.ebextensions config file that installs an OS package and sets an application environment variable in one go.
cat > .ebextensions/02_packages_env.config <<'EOF'
packages:
yum:
htop: []
option_settings:
aws:elasticbeanstalk:application:environment:
LAB_FEATURE_FLAG: "enabled"
EOF
Two new keys exist under .ebextensions: an OS package to install via yum and a new environment variable, both scoped to this application bundle.
eb deploy eb-lab-envDeploy succeeds; because an environment variable changed, Beanstalk performs a configuration update/instance replacement following the currently configured deployment policy (Immutable, from Exercise 2) rather than an instant in-place change.
eb ssh eb-lab-env # on the instance: rpm -q htop exit
rpm -q htop returns an installed package version instead of "package htop is not installed" — confirming the packages block ran on the instance.
eb printenv eb-lab-env
LAB_FEATURE_FLAG = enabled appears in the printed environment variable list, matching what process.env.LAB_FEATURE_FLAG would return inside the running application.
eb terminate eb-lab-env --region eu-west-1The environment, its Auto Scaling group, load balancer, and instances are torn down; the application and its stored versions in S3 remain unless you also delete the application itself.
This is the hands-on version of two frequently-tested traps: environment variable changes are configuration changes, not instant edits — you just watched one ride along on the currently-configured deployment policy — and .ebextensions is the version-controlled, repeatable way to install packages/set config without a custom AMI, which is exactly the "no custom AMI" exam cue from the Exam Logic tab.
Click card to flip. Mark right or wrong to track score.
DVA-C02 scenario style, Easy → Specialty. Select an answer to reveal the explanation.