Course outline

9.4

Elastic Beanstalk

Applications, versions and environments, web vs worker tiers, and single-instance vs HA deployments.

18 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain the problem Elastic Beanstalk solves for developers, and place it between EC2 by hand and Lambda on the managed-versus-control spectrum.
  • Describe applications, application versions and environments, environment names, URLs and tiers, and the platforms Beanstalk runs today.
  • List what one environment creates in your account through CloudFormation, what you pay for, and how to customise it safely with configuration options, .ebextensions and platform hooks.
  • Choose between a single-instance and a load-balanced environment, and explain why a production database should not live inside the environment.
  • Explain how the worker tier uses SQS: the daemon, visibility timeout, retries, the dead-letter queue and cron.yaml.
  • Compare the five deployment policies and blue/green by downtime, capacity, time and rollback, calculate batches and peak instance counts, and predict what each one does when the new version is broken.

#The developer’s problem

#Every web app needs the same plumbing

The last three lessons built the same kind of system again and again. For the “what time is it?” site (lesson 9.1) and the clothing shop (lesson 9.2) you put a load balancer in front of an Auto Scaling group across several AZs, added health checks, security groups chained from tier to tier, and a database. For the WordPress blog (lesson 9.3) you added shared storage and learned to launch instances fast.

That design is right for most web applications, and that is exactly the problem. A developer who only wants their code to run has to:

  • build and manage the infrastructure: VPC choices, security groups, load balancer, launch template, Auto Scaling group;
  • find a way to deploy new code to every instance without breaking the site;
  • configure the database, the load balancer listeners, the health checks and the alarms;
  • think about scaling: which metric, which limits, which AZs;
  • and do it consistently for every application and every environment (dev, test, prod), so that “it worked in test” means something.

Each team would rebuild the same ALB + ASG pattern by hand, slightly differently each time. AWS Elastic Beanstalk is AWS’s answer: a developer-centric way to deploy an application, in which you hand over the code and Beanstalk builds and runs that standard architecture for you.

#Where Beanstalk sits between EC2 and Lambda

Beanstalk is a PaaS (Platform as a Service, lesson 1.1): you manage the application code and its settings; AWS manages the platform under it. It helps to see it on a line from “I do everything” to “I do almost nothing”.

EC2 by hand (lessons 4–6)Elastic BeanstalkLambda (serverless)
You provideAMI, launch template, ALB, ASG, scaling, deployment scriptsCode (a zip, a WAR, or a Docker image definition) and settingsOne function per event
ServersYour EC2 instancesYour EC2 instances, created and managed for youNone you can see
OS accessFullFull (you can log in to the instances)None
ScalingYou configure the ASGBeanstalk configures the ASG; you set the limitsAutomatic, per request
DeploymentYour own toolingBuilt-in policies (all at once, rolling, immutable…)Upload a new version
BillingInstance hours + everything elseThe same resources at the same prices; Beanstalk adds nothingPer request and duration
Best forUnusual architectures, total controlStandard web apps and workers, fastEvent-driven, spiky, short tasks

The notes give three reasons to choose Beanstalk:

  1. Fast deployment: code goes straight to a production-shaped environment in minutes.
  2. Full control: unlike serverless, Beanstalk does not lock you out. The EC2 instances and the load balancer it creates are visible in your account, and you can log in to the instances and change them. (The next section explains the catch.)
  3. Free service: there is no charge for Beanstalk itself; you pay only for the resources it creates.

#What it costs

Elastic Beanstalk itself is free. The bill is the sum of what it creates: EC2 instances (On-Demand by default, Spot or a Savings Plan if you configure them, lesson 4.4), the load balancer, EBS volumes, the S3 storage for your application versions and logs, CloudWatch alarms and, if you add one, an RDS database. Two environments cost twice as much, which matters for blue/green deployments later in this lesson.

#Applications, versions and environments

#The three building blocks

  • Application: a named container for everything that belongs to one piece of software: its versions, its environments and its saved configurations. It runs nothing and costs nothing.
  • Application version: one specific build of your code, a source bundle (a zip or WAR file) that Beanstalk stores in S3 with a label such as v42. Versions belong to the application, not to an environment, so you can deploy the same version to test and later to prod. The default quota is 1,000 application versions per Region across all applications; a version lifecycle policy deletes old ones automatically.
  • Environment: a set of AWS resources running one application version at a time. You usually have several per application: shop-dev, shop-test, shop-prod. Each has its own configuration, resources and URL.

Around them sit saved configurations (templates of environment settings you can reuse) and the platform the environment runs on. The workflow is always the same: create the application, upload a version, launch an environment, then manage it; to release, you upload a new version and deploy it to the environment.

From an application down to your code

Every Beanstalk environment is a stack of layers. You write only the innermost one; Beanstalk builds and looks after the rest.

Scenario

Application: shopa folder for versions, environments and saved configurations
Step 1 of 6
1

An application is only a container with a name. It costs nothing and runs nothing. It groups everything that belongs to one piece of software.

#Environment names, URLs and tiers

When you create an environment you choose:

  • an environment name, unique within the application, such as shop-prod;
  • a domain prefix (CNAME prefix), unique within the Region. The environment URL becomes shop-prod.us-east-1.elasticbeanstalk.com. For a load-balanced environment it is a DNS name that points at the load balancer; for a single-instance environment, at the instance’s Elastic IP. You normally put your own name in front of it, www.example.com, with a Route 53 alias record that targets the environment (lesson 8.2) or a CNAME to the environment URL;
  • a tier: web server (it answers HTTP or HTTPS from users) or worker (it processes jobs from an SQS queue and has no public URL of its own). Tiers get their own section below.

#Platforms you can run

A platform is the software stack on the instances: operating system, language runtime, web server or proxy, and Beanstalk’s agents. The current list (October 2026):

  • Docker (Docker running on Amazon Linux 2023) and ECS running on Amazon Linux 2023 (several containers per instance, managed by an ECS agent; it replaced “multi-container Docker”);
  • Go, Java (plain Java apps on Amazon Corretto), Tomcat (Java web apps as WAR files);
  • .NET Core on Linux and .NET on Windows Server (IIS);
  • Node.js, PHP, Python, Ruby.

A few terms matter in practice:

  • A platform branch is a major line, such as “Node.js 22 running on 64bit Amazon Linux 2023”. A platform version inside it is numbered major.minor.patch, for example 6.11.12.
  • Managed platform updates apply new minor and patch versions automatically in a weekly two-hour maintenance window, using an immutable update so capacity never drops. Console-created environments have them on by default. They never cross to a new branch; when a branch retires, you migrate yourself, usually with a blue/green deployment.
  • Docker is the escape hatch: if your language or stack is not on the list, put it in a container.

#What Beanstalk builds in your account

#One environment, one CloudFormation stack

Beanstalk does not have its own hidden servers. For every environment it writes an AWS CloudFormation template and creates a stack in your account (CloudFormation, AWS’s infrastructure-as-code service, has its own chapter near the end of the course). The notes put it simply: Beanstalk uses CloudFormation under the hood. A load-balanced web server environment typically contains:

  • an S3 bucket named elasticbeanstalk-<region>-<account-id> (one per Region, shared by your applications) holding your source bundles and logs;
  • security groups: one for the load balancer, one for the instances that allows traffic only from the load balancer (the tier-to-tier chaining of lesson 9.2);
  • an Elastic Load Balancer: an Application Load Balancer by default from the console and the EB CLI (Network and Classic are options, and several environments can share one ALB);
  • a launch template and an Auto Scaling group across the AZs you choose, by default minimum 1 and maximum 4 instances;
  • CloudWatch alarms that drive scaling. The default trigger is network traffic out of the instances (scale out above 6 MB, in below 2 MB, over 5 minutes); most teams switch to CPU or request count;
  • for a single-instance environment, an Elastic IP instead of the load balancer;
  • optionally an RDS DB instance (see “Keep the database out of the environment” below).

Beanstalk also needs two IAM roles: a service role that lets Beanstalk call other services for you, and an instance profile that lets the instances read the bundle from S3, upload logs and report health. The console and EB CLI create both on first use.

What one environment builds

The developer hands over a zip. Beanstalk stores it in S3 and asks CloudFormation to build everything else in your account.

Scenario

eb create with the defaults: a load-balanced web server environment across two AZs.

us-east-1
AZ a
AZ b
Users
S3 bucket
Developer
Beanstalk
CloudFormation
shop-v1.zip
Step 1 of 7
1

The developer runs eb create shop-prod. The EB CLI zips the project folder into a source bundle and sends it to Beanstalk. Nothing exists in the Region yet.

#Changing the configuration: options, .ebextensions and platform hooks

Everything about an environment is a configuration option in a namespace, for example aws:autoscaling:asg → MinSize, or aws:elasticbeanstalk:command → DeploymentPolicy. You can set options in four places, and the first one that sets an option wins:

  1. directly on the environment (console, EB CLI, API);
  2. a saved configuration you applied;
  3. configuration files in your source bundle;
  4. the defaults.

Inside the source bundle you can customise the instances and the environment:

  • .ebextensions/*.config (YAML or JSON): option_settings, packages to install, files to write, commands and container_commands to run, and even extra Resources in CloudFormation syntax (an SQS queue, a DynamoDB table);
  • .platform/hooks/ (prebuild, predeploy, postdeploy) and .platform/confighooks/: scripts that run at fixed points of a deployment on Amazon Linux 2023 platforms; .platform/nginx/ overrides the proxy configuration;
  • a Procfile for the command that starts your app, and environment properties (environment variables) for settings such as feature flags or a database endpoint.

#Full control, with one catch

You really do have OS-level access: eb ssh logs you in to an instance, and you can change anything. But instances are disposable. An Auto Scaling scale-in, a failed health check, an immutable deployment or a managed platform update replaces them with fresh ones built from the platform AMI and your source bundle, and every change you made by hand is gone. The same is true of the resources in the stack: if you edit the load balancer or the security groups in their own consoles, the next environment update can put them back.

So “full control” means: any change you want, as long as it lives in your source bundle or your environment configuration. That rule is the same lesson 4.3 taught about AMIs and user data: anything not in the recipe does not survive a relaunch.

#Single-instance or load-balanced

The slides call these the two deployment modes; in the console and the API they are environment types.

Single instance: great for devLoad-balanced (high availability): great for prod

  • One EC2 instance, in an Auto Scaling group with minimum and maximum both 1
  • An Elastic IP on the instance; the environment URL points to it
  • No load balancer, so it is cheap
  • No redundancy: if the instance or its AZ fails, the site is down until the ASG replaces it
  • Deployment policies: all at once and immutable only
  • eb create --single
  • An ALB (by default) in front of an Auto Scaling group across two or more AZs
  • Health checks, automatic replacement and scaling on CloudWatch alarms
  • Set the minimum to 2 or more for real high availability: the default minimum of 1 is still a single point of failure
  • All five deployment policies, and blue/green
  • eb create (the default type)

A common pattern is one cheap single-instance environment per developer or per feature branch, and a load-balanced environment for staging and production, all running the same application versions.

#Keep the database out of the environment

The slide for the HA mode shows an RDS primary and standby inside the environment, and Beanstalk can indeed create an RDS database as part of the environment (MySQL, PostgreSQL, Oracle or SQL Server). It then passes the connection details to your code as environment properties: RDS_HOSTNAME, RDS_PORT, RDS_DB_NAME, RDS_USERNAME, RDS_PASSWORD. That is called a coupled database, and it is handy for a first test.

For production it is a trap, because a coupled database shares the environment’s lifecycle:

  • When the environment is terminated, the stack deletes what it created. The database follows its deletion policy: Delete (the default), Snapshot (take a final snapshot, then delete) or Retain (keep it running).
  • Blue/green needs two environments that both talk to the same production database. A database that belongs to one of them cannot be shared that way.
  • Other environments, other applications or a reporting tool cannot use it cleanly, and settings changed in the RDS console are overwritten by the environment’s own.

The fix is to decouple it: create the RDS database (Multi-AZ, lesson 7.1) outside Beanstalk, or decouple an existing one with the Retain policy, then give the environment the endpoint through environment properties or AWS Secrets Manager, and allow the instances’ security group in the database’s security group. Apply the deletion policy change first, as its own update, and decouple in a second one: if you submit both together, the old policy wins.

#Web server tier and worker tier

#The web server environment

A web server environment is what you have seen so far: it has a URL, receives HTTP and HTTPS requests from the internet through its load balancer, and runs them on the instances in its Auto Scaling group. Its job is to answer users quickly.

Some work does not fit inside a request: converting a video, building a large report, resizing photos, sending a batch of emails, calling a slow partner API. Done inside the web request, each one makes the user wait, ties up a web server, and under load can starve the requests that should be fast.

#The worker environment and its SQS daemon

A worker environment runs those jobs in the background. It has no public URL. The pieces are:

  1. The web tier puts a message on an Amazon SQS queue with the AWS SDK, for example {"video": 42}, and immediately answers the user (often with HTTP 202 Accepted). SQS, AWS’s managed message queue, gets a full chapter later (chapter 13); here you need only the basics.
  2. Beanstalk creates the queue for you (an autogenerated standard queue) or uses an existing one, standard or FIFO.
  3. On every worker instance, Beanstalk runs the SQS daemon (sqsd). It pulls messages from the queue and, for each one, sends an HTTP POST to http://localhost/ on port 80 (the path is configurable), with the message body as the request body and SQS details in X-Aws-Sqsd-* headers.
  4. Your worker code is therefore just a web handler. If it returns 200 OK, the daemon deletes the message. Any other status, or no answer, means failure, and the message comes back for another try.

This is decoupling: the web tier can absorb a burst of uploads instantly, the queue holds the backlog, and the workers process it at their own pace without being overwhelmed. Messages also survive worker failures, which is the topic of the next part.

#Timeouts, retries and the dead-letter queue

  • Visibility timeout (default 300 seconds, up to 12 hours): when a daemon receives a message, SQS hides it from everyone else for this long. If the job is not confirmed in time, the message becomes visible again and another worker gets it. Set it longer than your longest job, otherwise a slow job is processed twice.
  • Error visibility timeout: how long a message stays hidden after your code returns an error, before the next try.
  • Inactivity timeout: how long the daemon waits for your code to answer; raise it with the visibility timeout for long jobs.
  • Max retries (default 10, range 1–100): after that many failed attempts, the message moves to a dead-letter queue (DLQ). With an autogenerated queue the DLQ is set up for you; with your own queue you configure it in SQS. Without a DLQ, a message that always fails cycles until its retention period (4 days by default) runs out.
  • SQS delivers at least once: even with good settings, a message can be processed twice (for example when an instance dies just after finishing). Make jobs idempotent, so running one twice does no harm.

#Periodic tasks with cron.yaml

A cron.yaml file in the worker’s source bundle defines scheduled jobs: a name, a URL path and a cron expression (times are in Coordinated Universal Time). Exactly one instance, the leader, enqueues each task when it is due; the instances elect the leader by writing to a DynamoDB table, and if the leader dies another takes over. Any worker then processes the message, like any other job. Periodic tasks are not supported with a FIFO queue.

version: 1
cron:
  - name: "nightly-report"
    url: "/tasks/report"
    schedule: "0 2 * * *"

#Scaling the workers

A worker environment has its own Auto Scaling group. Its default scaling triggers are the same generic instance metrics as a web environment, but the real signal for a worker is the queue: how many messages are waiting per instance. Add a CloudWatch alarm or a target tracking policy on the SQS metric ApproximateNumberOfMessagesVisible divided by the number of instances, the “backlog per instance” method from lesson 6.5. A worker that waits on a slow external API can have a growing queue and low CPU at the same time, so CPU-based scaling would never react.

Web tier → SQS → worker tier

The web tier answers users fast and drops slow jobs into an SQS queue. A daemon on every worker instance pulls each message and POSTs it to your code on localhost.

Scenario

Web server environment
Worker environment
User
Web server
SQS queue
DLQ
Worker 1
Worker 2
POST /upload
Step 1 of 6
1

A user uploads a video. Converting it takes minutes, far too long to keep an HTTP request open, and it would tie up the web server.

#Deploying a new version

You upload v2 and deploy it to an environment that runs v1. How v2 reaches the instances is the deployment policy, set per environment (option DeploymentPolicy in aws:elasticbeanstalk:command). There are five built-in policies. The notes list four; the fifth, traffic splitting, is just as examinable. Blue/green is not a policy at all, but a pattern with two environments, covered in the next section.

#All at once

Beanstalk installs v2 on every instance at the same time. The application servers restart, so for a short time nothing is in service.

  • Fastest deployment, no extra instances, no extra cost.
  • Downtime during the deployment. If v2 is broken, the whole fleet is broken: a full outage until you redeploy v1 manually.
  • Use it for development and test, or when a short outage is acceptable. It is Beanstalk’s default policy, except that a load-balanced environment created with the EB CLI starts with rolling.

#Rolling

Beanstalk splits the instances into batches and updates one batch at a time. For each batch it takes the instances out of the load balancer (draining connections), deploys v2, waits for them to pass health checks, and puts them back.

  • No downtime, but capacity drops by one batch for the whole deployment, so plan for it at peak hours.
  • Batch size is a percentage of the instances or a fixed number.
  • For a while, v1 and v2 serve users side by side, so both must work with the same database schema and APIs.
  • If a batch fails its health checks within the command timeout, the deployment stops: completed batches run v2, the rest run v1. There is no automatic rollback; you deploy a known good version again.
  • Not available for single-instance environments.

Calculating it: 8 instances with a 25% batch size = 2 instances per batch = 4 batches, and only 6 of 8 instances (75%) serve during the deployment. With a batch size of 50% it is 2 batches, faster, but only 4 of 8 serve.

Self-checkQuestion

An environment runs 6 instances with the Rolling policy and a fixed batch size of 2. How many batches does a deployment take, and how many instances are in service while a batch is being updated?

#Rolling with additional batch

The same as rolling, except that Beanstalk first launches one extra batch of new instances with v2. Then it rolls through the existing instances, and at the end it terminates an extra batch’s worth of instances.

  • Full capacity throughout: the in-service count never drops below the original. Use it when a rolling deployment’s lost capacity would hurt.
  • Slightly more cost (the extra batch runs for the length of the deployment) and a longer deployment than rolling.
  • If the very first (new) batch fails, impact is minimal because no existing instance was touched; if a later batch fails, you are in the same partial state as a failed rolling deployment. Rollback is a manual redeploy.
  • Calculating it: 8 instances, batch 25% → Beanstalk adds 2, so up to 10 instances run and 8 are always in service.

#Immutable

Beanstalk never touches the existing instances. Instead:

  1. It creates a temporary Auto Scaling group behind the same load balancer and launches one instance with v2.
  2. When that instance passes health checks, it launches enough instances to match the original group.
  3. When all of them are healthy, it moves the new instances into the original Auto Scaling group, then terminates the old instances and the temporary group.

Properties:

  • Zero downtime, full capacity, and every v2 instance is brand new: no half-updated instance, no leftovers from v1.
  • For a short time the environment runs double the instances (8 become 16), so check your EC2 On-Demand quota on a big fleet. It is the slowest of the policies inside one environment, and instances lose their accumulated burst credits.
  • Rollback is quick and automatic: if the new instances fail their health checks, Beanstalk terminates the temporary group. The original instances never stopped serving v1.
  • It requires enhanced health reporting, and it works on single-instance environments too.

The notes describe immutable as “a whole new ASG; delete the old one after tests pass”. More precisely, the original ASG survives: the new instances are moved into it, and it is the temporary group and the old instances that are deleted.

#Traffic splitting

Traffic splitting is a canary deployment built into Beanstalk:

  1. Like immutable, Beanstalk launches a full set of new instances in a temporary Auto Scaling group.
  2. The load balancer sends a percentage of requests to the new instances (NewVersionPercent, default 10%) for an evaluation time (default 5 minutes, range 3–600).
  3. If the new instances stay healthy, all traffic moves to them, they join the original ASG, and the old instances and the temporary group are removed. If they become unhealthy, or you abort, Beanstalk moves all traffic back to v1 and terminates the new instances.

Only the canary share of users can see a broken v2, and the rollback is automatic. Traffic splitting needs an Application Load Balancer, which does the split much like the weighted target groups of lesson 6.3, and is not available for single-instance environments.

#The five policies side by side

PolicyDowntimeCapacity during deployExtra instancesDeploy timeIf v2 failsRollbackv2 runs on
All at onceYes0 for a short timeNoneFastestFull outageManual redeployExisting instances
RollingNoReduced by one batchNoneModerate (depends on batch size)One batch out; finished batches on v2Manual redeployExisting instances
Rolling with additional batchNoFullOne batchLongerMinimal if the first batch fails, else like rollingManual redeployNew and existing
ImmutableNoFull, doubled brieflyA full setSlowestMinimalTerminate new instances (automatic)New instances
Traffic splittingNoFull, doubledA full setSlowest (plus evaluation time)Canary share affectedReroute and terminate (automatic)New instances
Blue/green (pattern)NoFull, two environmentsA whole environmentSlowestMinimal (caught before the swap)Swap URLs backA new environment

None of the five built-in policies changes DNS; only blue/green does.

Try every policy with a working and a broken v2:

Deployment policy simulator

Four instances serve v1. Pick a policy, choose whether v2 is broken, and press play. Watch where v2 runs, how much capacity is left, and how each policy fails.

Deployment policy

Batch size

Version 2

Environment’s ASG

v1v1v1v1

v1 · v2 · deploying (out of service) · launching · broken v2 · terminated

Time

0 min

Healthy in service

4 / 4

Instances running

4

Requests now

v1 100%
Step 1 / 3
1

Four instances serve v1 behind the load balancer. You run eb deploy with v2 and the All at once policy.

#Blue/green: a second environment and a URL swap

The safest release keeps the whole old environment ready to take traffic back. That is blue/green, and in Beanstalk it is a manual pattern, not a deployment policy:

  1. Blue (shop-prod) serves production with v1.
  2. You clone it, or create a new environment, as green (shop-green) and deploy v2 there. Green has its own URL, load balancer and instances.
  3. You test green through its own URL while users stay on blue.
  4. You choose Swap environment URLs (eb swap, or the SwapEnvironmentCNAMEs API). Beanstalk swaps the CNAME records of the two environments: shop-prod.us-east-1.elasticbeanstalk.com now points at green’s load balancer.
  5. If something goes wrong, you swap again. Blue never stopped.

Use blue/green when a deployment policy cannot do the job: moving to a new platform branch, changing settings that cannot be changed in place, or when you need the old environment intact as the fastest way back.

The caveats:

  • DNS caching. The swap changes a DNS record, so it moves users only as fast as resolvers drop the old answer. Some users keep reaching blue for the TTL of the record (lesson 8.1), and some resolvers and clients cache longer than the TTL. AWS’s advice: do not terminate the old environment until the old DNS records have expired. The rollback swap has the same delay.
  • Your own domain must follow. If www.example.com is a Route 53 alias to the environment (or a CNAME to the environment URL), it follows the swap. If someone pointed it straight at blue’s load balancer DNS name, the swap does nothing for your users.
  • Shared database. Both environments must use the same database outside Beanstalk (the coupled database problem from earlier).
  • Cost. You pay for two full environments while both run.

When you need an instant, per-request switch rather than a DNS one, use traffic splitting inside the environment, or Route 53 weighted records (lesson 8.3) in front of the two environments for a gradual DNS-level shift.

Blue/green: swapping environment URLs

Two complete environments. The production name is a DNS record, and swapping it moves users, but only as fast as DNS caches let it.

Scenario

Blue: shop-prod
User A
User B
DNS
ALB · v1
shop-prod?
Step 1 of 4
1

User A looks up shop-prod.us-east-1.elasticbeanstalk.com. That name is a CNAME record that points at the blue environment’s load balancer.

#Health and automatic rollback

#Basic and enhanced health

Every environment shows a health colour: green (OK), yellow (warning), red (degraded or severe) or grey (unknown, or an update in progress).

  • Basic health uses the load balancer’s health checks (or, for a single instance, EC2 status checks) and a few CloudWatch metrics published every 5 minutes.
  • Enhanced health adds a health agent on every instance that reports OS metrics, web server logs (request counts, 4xx and 5xx rates, latency) and deployment status to Beanstalk every 10 seconds, with statuses such as Ok, Warning, Degraded and Severe and a “cause” for each. It is on by default for environments created in the console, it is free unless you publish its metrics to CloudWatch, and immutable deployments and managed platform updates require it. eb health shows it live.

Set a proper health check URL (a path such as /health that really exercises the app). Without one, an instance counts as healthy as soon as it accepts a TCP connection, possibly before the app has started.

#What happens when a deployment fails

During a deployment, each batch (or each new group of instances) must become healthy within the command timeout (default 600 seconds, plus a fixed four minutes Beanstalk adds). With enhanced health, a web instance must pass 12 consecutive checks over two minutes. Then:

  • All at once, rolling, rolling with additional batch: the deployment fails and stops where it is. Nothing is undone automatically; the deployment ID on each instance shows which version it runs, and you redeploy a good version to roll back.
  • Immutable: Beanstalk terminates the temporary Auto Scaling group; logs from the failed instances stay in S3 for an hour so you can see why.
  • Traffic splitting: Beanstalk shifts all traffic back to the old instances and terminates the new ones.
  • Two settings change this: Healthy threshold lets instances pass at a lower level (for example Warning), and Ignore health check deploys regardless of health. Both trade safety for speed.

#Exam patterns at a glance

#Beanstalk in system design

  • It is the 9.1–9.3 architecture, packaged. ALB across AZs, an ASG with health checks, security groups chained tier to tier: Beanstalk builds exactly what you designed by hand. Your design work moves to choosing settings: minimum of 2 or more, multi-AZ subnets, a scaling metric that matches the load, a health check URL.
  • Keep instances stateless. Every deployment policy except all at once replaces or recycles instances, so sessions belong in ElastiCache or DynamoDB (lesson 9.2), uploads in S3 or EFS (lesson 9.3), and the database outside the environment.
  • Pick the policy by risk. Dev: all at once or single instance. Production web: immutable or traffic splitting, with rolling with additional batch when cost matters more. Platform-branch migrations and risky changes: blue/green.
  • Split by tier. Fast requests in the web tier, slow work through SQS into a worker tier that scales on queue depth. Several applications can share one queue pattern with different paths.
  • Know when to move on. Microservices with many containers usually outgrow Beanstalk for ECS or EKS (chapter 14); event-driven glue fits Lambda better (chapter 15); a full infrastructure-as-code setup with CloudFormation or the CDK gives you everything Beanstalk does, with more work and more control.

#Try it yourself

With the EB CLI (pip install awsebcli) in a project folder:

# 1. Create the application (asks for Region and platform) and a cheap dev environment
eb init shop --platform node.js --region us-east-1
eb create shop-dev --single                 # one instance + Elastic IP, no load balancer

# 2. A production environment with an Application Load Balancer
eb create shop-prod --elb-type application

# 3. Ship a new version, watch health, read logs, log in
eb deploy shop-prod                         # zips, uploads to S3 as a new version, deploys
eb health shop-prod                         # enhanced health, refreshed live
eb logs shop-prod
eb ssh shop-prod                            # OS access (changes made here do not survive)

# 4. Environment properties (environment variables) for the app
eb setenv DB_HOST=shop-db.abc123.us-east-1.rds.amazonaws.com FEATURE_X=on

# 5. Blue/green: clone, deploy v2 to the clone, test it, swap the URLs
eb clone shop-prod --clone_name shop-green
eb deploy shop-green
eb swap shop-prod --destination_name shop-green

# 6. A worker environment for background jobs
eb create shop-worker --tier worker

The same with the AWS CLI:

# Upload a version from S3 and deploy it with the Immutable policy
aws elasticbeanstalk create-application-version --application-name shop \
  --version-label v42 --source-bundle S3Bucket=my-builds-bucket,S3Key=shop-v42.zip
aws elasticbeanstalk update-environment --environment-name shop-prod --version-label v42 \
  --option-settings Namespace=aws:elasticbeanstalk:command,OptionName=DeploymentPolicy,Value=Immutable

# Real high availability: at least two instances
aws elasticbeanstalk update-environment --environment-name shop-prod \
  --option-settings Namespace=aws:autoscaling:asg,OptionName=MinSize,Value=2

# Health, events and the URL swap
aws elasticbeanstalk describe-environment-health --environment-name shop-prod --attribute-names All
aws elasticbeanstalk describe-events --environment-name shop-prod --max-items 20
aws elasticbeanstalk swap-environment-cnames \
  --source-environment-name shop-prod --destination-environment-name shop-green

# What did the environment create? (the stack is named after the environment ID)
aws elasticbeanstalk describe-environment-resources --environment-name shop-prod

A configuration file in the source bundle, .ebextensions/01-deploy.config:

option_settings:
  aws:elasticbeanstalk:command:
    DeploymentPolicy: TrafficSplitting
  aws:elasticbeanstalk:trafficsplitting:
    NewVersionPercent: "10"
    EvaluationTime: "5"
  aws:elasticbeanstalk:application:
    Application Healthcheck URL: /health
packages:
  yum:
    ImageMagick: []

And a platform hook that runs on every instance before the new version goes live, .platform/hooks/predeploy/01-migrate.sh:

#!/bin/bash
# Runs after the bundle is extracted, before the app starts serving
cd /var/app/staging && npm run migrate

#Summary

Key takeaways

  • Elastic Beanstalk is a developer-centric PaaS: you upload code, it builds and runs the standard ALB + ASG + EC2 architecture in your account through CloudFormation. Beanstalk is free; you pay for the resources. It is not serverless.
  • Full control: you can log in to the instances, but instances are replaced, so persistent changes go in .ebextensions, .platform hooks and configuration options.
  • Application (container) → application versions (source bundles in S3, quota 1,000 per Region) → environments (one version at a time, own URL name.region.elasticbeanstalk.com, tier).
  • Platforms: Docker and ECS on Amazon Linux 2023, Go, Java (Corretto), Tomcat, .NET (Linux and Windows/IIS), Node.js, PHP, Python, Ruby. Managed platform updates: minor and patch, weekly window, immutable.
  • Single instance (Elastic IP, no load balancer, dev) vs load-balanced (ALB, multi-AZ ASG, prod; set minimum ≥ 2). Keep RDS outside the environment; a coupled database is deleted with it by default.
  • Web tier answers users; worker tier takes jobs from SQS: the sqsd daemon POSTs to localhost, 200 → delete; visibility timeout longer than the job; max retries → DLQ; cron.yaml for schedules; scale on queue depth.
  • Five policies: all at once (fast, downtime), rolling (capacity − one batch, manual rollback), rolling with additional batch (full capacity, extra batch), immutable (temporary ASG, doubled briefly, automatic cheap rollback), traffic splitting (canary %, ALB, automatic rollback).
  • Blue/green = second environment + swap environment URLs (CNAME swap); keep the old one until DNS caches expire; point your domain at the environment, not the load balancer.
  • Enhanced health (agent every 10 s) is required for immutable and managed updates; failed rolling deployments need a manual redeploy.