
AWS Elastic BeanstalkAuthorCloudBrum editorial teamLast reviewedReading time~12 minLevelBeginner to advanced
Amazon Web Services · Compute · Platform for web applications
Upload your code, and AWS builds the servers around it. Elastic Beanstalk takes a zip file or a Docker image and sets up the EC2 instances, the load balancer, the Auto Scaling group and the health monitoring for it. Unlike most platform services it leaves every one of those resources visible in your account, so you can look at them and change them. The service itself costs nothing, and you pay for what it creates. Keep an eye on the platform version: AWS retired the last Amazon Linux 2 platform branches on 6 August 2026, and moving to a newer one means building a new environment.
On this page (17 sections)
Mind map: AWS Elastic Beanstalk at a glance
Free to share. The downloaded image includes the CloudBrum link.
Key features (summary)
- From code to running serversUpload a zip of your code, a WAR file or a Docker setup, choose a platform such as Python or Node.js, and Beanstalk creates the instances, the load balancer and the scaling rules. You never write the infrastructure template.
- Nothing is hiddenThe EC2 instances, the Auto Scaling group and the load balancer all appear in your account. You can inspect them, log in to an instance and tune settings that a more closed platform would not expose.
- Deployment policiesChoose how a new version rolls out: all at once, rolling in batches, rolling with an extra batch, immutable (a fresh set of instances), or traffic splitting for a canary release.
- Enhanced healthBeanstalk watches the instances and the load balancer and reports the environment as green, yellow, red or grey, with causes such as high latency or failing requests.
- Managed platform updatesWithin a weekly window Beanstalk can apply minor and patch platform updates for you, replacing instances in the way your deployment policy says.
- Configuration as filesOption settings, .ebextensions files and .platform hooks describe the environment inside your source bundle, so settings travel with the code.
- Web and worker environmentsA web environment serves HTTP behind a load balancer. A worker environment reads messages from an Amazon SQS queue and posts each one to your app, which suits background jobs.
- No charge for the serviceYou pay for the instances, load balancer, storage and data transfer that Beanstalk creates, and nothing for Beanstalk itself.
Basic concepts
- Application
- A logical folder for everything that belongs to one app: its versions, environments and saved configurations.
- Application version
- One uploaded, labelled bundle of code, stored in S3. An environment runs exactly one version at a time.
- Environment
- A running copy of an application version with its own instances, load balancer, URL and settings. You’d usually have one per stage, such as test and production.
- Environment tier
- Web server or worker. The web tier handles HTTP requests, and the worker tier processes messages from an SQS queue.
- Platform
- The operating system, runtime and web server that Beanstalk installs, such as Python on Amazon Linux 2023. Platforms have versions that are updated by AWS.
- Platform branch
- A line of platform versions for one runtime version, for example one Python minor version. A branch is retired when its operating system or runtime reaches end of life.
- Option settings
- Key and value settings, grouped by namespace such as aws:autoscaling:asg, that configure the environment.
- .ebextensions
- A folder of YAML or JSON configuration files in the source bundle that set options and customise resources and instances.
- .platform hooks
- Scripts and configuration under .platform in the bundle that run at set points of a deployment, and that replace most uses of .ebextensions commands on newer platforms.
- Deployment policy
- The rule for how a new version replaces the old one on the environment’s instances.
- Instance profile
- The IAM role that the EC2 instances assume, which gives the application its permissions to AWS services.
- Service role
- The IAM role that Beanstalk itself assumes to manage resources and health on your behalf.
- Managed action
- A maintenance task that Beanstalk can run for you in a weekly window, such as applying a platform update.
- CNAME swap
- An action that exchanges the URLs of two environments, used for blue/green deployments.
How to create & configure it
Deploy a web app to Elastic Beanstalk with the AWS CLI
- Choose the Region and the platformPick a Region near your users. Look up the current platform names with list-available-solution-stacks instead of copying an old one from a tutorial, and choose an Amazon Linux 2023 platform.
- Prepare the code bundlePut a Procfile (or the platform’s default entry point) in the project, add .ebextensions or .platform files if you need them, and zip the project so that the application files sit at the top level.
- Create the rolesMake a service role for Beanstalk and an instance profile for the instances. Give the instance role only what the app needs, plus the web tier managed policy.
- Upload the versionCopy the zip to S3 and register it as an application version with a clear label such as 1.4.2.
- Create the environmentRun create-environment with the platform, version label and option settings: instance type, scaling limits, load balancer type, deployment policy, health reporting and the VPC subnets.
- Wait and check healthCreation takes several minutes. Use aws elasticbeanstalk wait environment-exists, then read the health and the events if anything isn’t green.
- Add HTTPS and a domainAdd an HTTPS listener with a certificate from AWS Certificate Manager and point your domain at the environment’s load balancer.
- Deploy a new version safelyUpload the next version, then update the environment with it. Prefer an immutable or traffic-splitting policy for production, and test the rollback.
- Plan the platform updatesTurn on managed updates, check the platform release notes, and put the end-of-life dates of your platform branch in a calendar. Moving between operating system generations means a new environment.
Tip: the EB CLI (eb init, eb create, eb deploy) wraps these steps and is pleasant for a first environment. The AWS CLI version is longer, but it shows each setting once. See the code references for the same environment as Terraform.
Common issues after configuration
| Symptom | Likely cause | What to check / fix |
|---|---|---|
| The environment health is red after a deployment: Instance deployment failed | The app crashed at start-up, a hook failed, or the process listens on a different port than the platform expects | Download the logs (eb logs or the console), read eb-engine.log and the web server log, and check the Procfile and the port. Redeploy the previous version while you fix it. |
| 502 Bad Gateway from the load balancer or the proxy | The application isn’t running, or it takes too long to answer | Check that the process started and listens on the port the proxy forwards to, raise the idle or request timeout if the work is slow, and look at the application log. |
| Service:AmazonCloudFormation, Message:Template format error or a stack that fails to update | A bad option setting or an .ebextensions resource block breaks the underlying stack | Read the event that names the resource, fix the setting, and avoid custom resources in .ebextensions where an option setting exists. |
| The environment is stuck in Updating or Terminating | A rolling or immutable update waits for instances that never become healthy, or a resource can’t be deleted | Check the events, abort the update from the console if it’s safe, and fix the health problem before you retry. For deletions, find the resource that blocks, such as a security group in use. |
| The instance profile ... associated with the environment does not exist | The role or instance profile name is wrong, or the profile isn’t created yet | Create the instance profile, add the role to it, wait a few seconds and use its name in IamInstanceProfile. |
| Platform update fails or the new platform version breaks the app | A dependency, hook or file path assumes the old operating system | Test the new platform in a separate environment first, then use a blue/green swap. Don’t expect an in-place move between Amazon Linux generations. |
| Your platform branch is retired warnings | The environment runs on a branch whose operating system or runtime is end of life | Create a new environment on a supported branch, test it and swap the CNAME. Retired branches get no maintenance updates. |
| Deployments take too long | Large bundles, slow dependency installs on every instance or an immutable policy launching new instances | Reduce the bundle, vendor or cache dependencies, and choose rolling or traffic splitting where a fresh fleet is not needed. |
| The app can’t reach the database or the internet from private subnets | No NAT gateway or endpoint, or the security group blocks the traffic | Add a NAT gateway or VPC endpoints for the services you call, and allow the instances' security group in the database. |
| Environment variables aren’t visible to the app | They were set on a different environment, or the process was started before the change | Check the option settings of the right environment and redeploy so the instances restart with the new values. |
| Costs are higher than expected for a test app | A load-balanced environment runs two instances and a load balancer around the clock | Use a single-instance environment for development, terminate environments you don’t use and set an Auto Scaling schedule. |
Use cases: when and where to use it
Good fit
- Teams with a standard web app in Python, Node.js, Java, .NET, PHP, Ruby or Go who want to deploy by uploading code
- Moving a classic web application from a server to AWS with few code changes
- Apps that need access to the EC2 instances or the load balancer for tuning
- Background workers that read from an SQS queue, in the worker tier
- Test and staging environments that you can create and delete from a config file
- Teams that know EC2 and want a layer of automation, not a different model
Consider something else
- No servers and scale to zero → AWS Lambda, or a serverless container service
- Containers at scale with Kubernetes → Amazon EKS
- Full control of the server and everything on it → Amazon EC2
- A simple web service from a container image, now closed to new customers → AWS App Runner, or Amazon ECS Express Mode
- The same job on other clouds → compare Azure App Service and Google App Engine
Pros: why consider it?
Why teams choose it
- Fast route from code to a running, load-balanced app
- No charge for the service, and every resource it creates is visible and editable
- Several deployment policies, including immutable and traffic splitting
- Health reporting and managed platform updates
- Configuration lives in the code bundle as files
- Web and worker tiers in one service
Trade-offs to weigh
- Doesn’t scale to zero: instances and the load balancer cost money around the clock
- Platform branches are retired as their operating systems age, and moving means a new environment
- Customising with .ebextensions can get messy, and the underlying CloudFormation stack is easy to break
- Less modern than container platforms, and AWS’s newer services get more attention
- Instances are still yours to secure, patch with managed updates and size
- Limited fit for microservices at large scale
Common threats, vulnerabilities & risks
| Risk | Severity | Why it matters | Mitigation |
|---|---|---|---|
| Running on a retired platform branch | High | No maintenance updates arrive, and security fixes for the operating system and runtime stop. | Track end-of-life dates, test the next branch in a separate environment and swap when ready. |
| An overly broad instance profile | High | Anything that runs on the instance can use the role, so a compromised app can reach every service it allows. | Grant only the actions and resources the app needs, and review the role when features change. |
| A database created inside the environment | High | Deleting the environment deletes the database with it, and upgrades get entangled. | Create the database outside Beanstalk, and pass its address as an environment variable. |
| Secrets in .ebextensions or environment variables | Medium | They show up in the source bundle, the console and logs. | Read secrets from Secrets Manager or Parameter Store at start-up, using the instance role. |
| Public instances with open security groups | Medium | Instances reachable from the internet invite scans and direct attacks. | Put instances in private subnets behind the load balancer, and allow only the load balancer’s security group. |
| Unreviewed all-at-once deployments | Medium | A bad version takes the whole environment down at once. | Use rolling, immutable or traffic-splitting policies in production, and keep the previous version for rollback. |
| Heavy customisation of the underlying stack | Medium | Hand-edited resources drift from what Beanstalk expects, and updates fail. | Use option settings and hooks, and avoid changing Beanstalk-managed resources by hand. |
| Always-on cost for idle environments | Low–Med | Test environments bill for instances and load balancers even without traffic. | Terminate or schedule down test environments, and use single-instance mode for development. |
| No tested rollback or disaster plan | Low–Med | The first real failure is a bad moment to learn how to recover. | Practise redeploying a previous version and recreating the environment from saved configuration. |
Performance optimisation
- Choose the instance type from measurements, and test an ARM-based type if your dependencies support it, since it often costs less for the same work.
- Turn on Auto Scaling with a sensible minimum and maximum, and scale on a metric that tracks load, such as request count per target or CPU.
- Use an Application Load Balancer and tune the health check path so it’s cheap and quick.
- Serve static files from S3 and CloudFront and let the instances handle only dynamic requests.
- Keep the bundle small and install dependencies in a way that doesn’t repeat on every instance start, for example by vendoring them.
- Match the web server’s workers to the instance’s CPUs, for example gunicorn workers in a Procfile.
- Use connection pooling to the database, because every new instance opens its own connections.
- Watch enhanced health and CloudWatch metrics for latency and error spikes after each deployment.
Reduce monthly cost
FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for AWS Elastic Beanstalk.
- Know that Beanstalk itself is free: the bill is the EC2 instances, the load balancer, EBS volumes, S3 for versions, CloudWatch and data transfer.
- Use a single-instance environment for development and test, which skips the load balancer.
- Right-size instances from the CloudWatch graphs, and consider Graviton instance types where your platform supports them.
- Buy Savings Plans or Reserved Instances for the steady base load, and let Auto Scaling cover spikes with on-demand capacity.
- Use scheduled scaling to reduce capacity at night and weekends for internal apps.
- Terminate environments you don’t use, and delete old application versions, since each one is stored in S3.
- Add Spot Instances in the Auto Scaling mix for fault-tolerant worker environments.
- Compare the cost of the load balancer and NAT gateway with the instances, since they can outweigh a small app.
- Set log retention for CloudWatch Logs, and stop streaming logs you never read.
- Tag environments by team and project, and set a budget alert.
Prices for the underlying services come from AWS's public pages and differ by Region and over time. Check the live Elastic Beanstalk pricing page and the EC2, load balancer and data transfer pages before you plan around them (see Pricing).
Security optimisation
- Give the instances an instance profile with least privilege, and keep the service role to the managed policies Beanstalk needs.
- Run instances in private subnets behind the load balancer, and allow inbound traffic only from the load balancer’s security group.
- Use HTTPS with a certificate from AWS Certificate Manager, redirect HTTP to HTTPS and set a modern TLS policy on the listener.
- Keep secrets in Secrets Manager or Parameter Store, and fetch them at start-up with the instance role.
- Turn on managed platform updates so operating system and runtime patches arrive, and test new platforms in a separate environment.
- Use AWS WAF on the Application Load Balancer for public apps.
- Block SSH access and the key pair in production, and use Systems Manager Session Manager when you need a shell.
- Encrypt EBS volumes and S3 versions and turn on S3 block public access for the application bucket.
- Send logs and health events to CloudWatch, and alert on health changes and failed deployments.
- Record API activity in CloudTrail, and review who can create, change or terminate environments.
Governance & compliance
Guardrails
- Tagging rules for applications and environments (owner, environment, cost centre) checked at creation
- A service control policy that blocks environments without a managed update window or with public instance addresses in production
- A shared Terraform module for environments, with HTTPS, private subnets, enhanced health and an immutable policy already set
- A list of approved platform branches with an end-of-life date for each, and an owner for every environment that still runs on one that is ageing
Continuous checks (AWS Config)
- “elasticbeanstalk-managed-updates-enabled”
- “elasticbeanstalk-enhanced-health-reporting-enabled”
- “elb-tls-https-listeners-only” on the environment’s load balancer
- “ec2-instance-no-public-ip” for the environment’s instances
- “s3-bucket-public-read-prohibited” on the application version bucket
AWS CloudTrail records who created, changed or terminated environments, Beanstalk events and enhanced health show what happened on them, AWS Config checks the configuration rules above, and AWS Artifact holds compliance reports. AWS maintains the platform images and the management service, while you own the application code, the instance role, the network design, the choice of when to update and the move off a platform branch before it retires.
Reduce carbon footprint
- Right-size instances, and use ARM-based types where they fit, since they do more work per watt.
- Scale down at night and weekends for internal apps, so fewer instances run for nothing.
- Terminate unused environments and delete old application versions.
- Serve static files from a cache close to users, so instances do less work.
- Keep dependencies lean and bundles small, so fewer bytes are moved and installed on each deployment.
- Choose a Region with a cleaner grid for workloads that aren’t tied to a place, as far as data rules allow.
- AWS’s Customer Carbon Footprint Tool gives account-level emission estimates. Check whether Beanstalk usage is itemised before you quote a figure.
Pricing
Purchase options
Elastic Beanstalk No charge
AWS charges nothing for Elastic Beanstalk itself. You pay for the AWS resources that your environments use.
Compute Per instance-second
The EC2 instances in the Auto Scaling group are billed at their normal rates, with Savings Plans, Reserved Instances and Spot discounts available.
Load balancing and network Per hour and per use
A load-balanced environment adds an Application Load Balancer, NAT gateways in private subnets, and data transfer.
Everything around it Varies
EBS volumes, S3 storage for application versions and logs, CloudWatch metrics and logs, and any RDS or other service you add.
What you actually pay for
- EC2 instances for every environment, around the clock unless you scale down
- An Application Load Balancer and any NAT gateways or endpoints
- EBS volumes, S3 storage for versions and CloudWatch logs
- Data transfer out and between Availability Zones
- Databases and other services that the application uses
AWS says there is no additional charge for Elastic Beanstalk, and rates for the underlying services differ by Region and change over time. See the official AWS Elastic Beanstalk pricing page, the AWS Pricing Calculator and the release note on the retired Amazon Linux 2 platform branches for platform status.
Important code references
A Python web app called orders-api as a load-balanced Beanstalk environment on Amazon Linux 2023: two to six instances in private subnets behind a public Application Load Balancer, immutable deployments, enhanced health, managed updates and an instance role that can write receipts to S3. The AWS CLI tab creates it, and Terraform creates the same environment. The Python tab deploys a new version and waits for the environment to settle, and the C# tab reports health and recent warnings for every environment. Replace the account, VPC, subnets, bucket and certificate with your own. A load-balanced environment bills from the moment it starts, so terminate the test one when you’re done.
# Placeholders: replace the account, VPC, subnets, bucket and certificate with your own. Run it from the folder that holds the app.
REGION=ap-south-1
ACCOUNT=111122223333
BUCKET=orders-eb-versions-example
RECEIPTS=orders-receipts-example
VPC=vpc-0123456789abcdef0
PRIVATE_SUBNETS=subnet-0aaa1111bbbb2222c,subnet-0ddd3333eeee4444f
PUBLIC_SUBNETS=subnet-0eee5555ffff6666a,subnet-0999aaaabbbbcccc1
CERT_ARN=arn:aws:acm:$REGION:$ACCOUNT:certificate/00000000-0000-0000-0000-000000000000
# 1. Roles. The service role lets Beanstalk manage health and updates. The instance profile is what the app itself may do.
aws iam create-role --role-name eb-orders-service --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{"Effect": "Allow", "Principal": {"Service": "elasticbeanstalk.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
for P in service-role/AWSElasticBeanstalkEnhancedHealth service-role/AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy; do
aws iam attach-role-policy --role-name eb-orders-service --policy-arn arn:aws:iam::aws:policy/$P
done
aws iam create-role --role-name eb-orders-instance --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{"Effect": "Allow", "Principal": {"Service": "ec2.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
aws iam attach-role-policy --role-name eb-orders-instance --policy-arn arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier
aws iam put-role-policy --role-name eb-orders-instance --policy-name receipts-write --policy-document '{
"Version": "2012-10-17",
"Statement": [{"Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::'$RECEIPTS'/receipts/*"}]}'
aws iam create-instance-profile --instance-profile-name eb-orders-instance
aws iam add-role-to-instance-profile --instance-profile-name eb-orders-instance --role-name eb-orders-instance
# 2. The bundle: a Procfile tells the platform how to start the app.
echo 'web: gunicorn --bind :8000 --workers 3 app:app' > Procfile
zip -r orders-1.4.2.zip . -x '*.git*' '*.pyc' '__pycache__/*'
aws s3 cp orders-1.4.2.zip s3://$BUCKET/orders-api/orders-1.4.2.zip
# 3. Look up a current Amazon Linux 2023 Python platform instead of copying an old name.
STACK=$(aws elasticbeanstalk list-available-solution-stacks --region $REGION \
--query "SolutionStacks[?contains(@, 'Amazon Linux 2023') && contains(@, 'Python')] | [0]" --output text)
echo "platform: $STACK"
aws elasticbeanstalk create-application --region $REGION --application-name orders-api
aws elasticbeanstalk create-application-version --region $REGION --application-name orders-api --version-label 1.4.2 \
--source-bundle S3Bucket=$BUCKET,S3Key=orders-api/orders-1.4.2.zip
# 4. The environment settings, as option settings.
cat > options.json <<EOF
[
{"Namespace": "aws:autoscaling:launchconfiguration", "OptionName": "IamInstanceProfile", "Value": "eb-orders-instance"},
{"Namespace": "aws:autoscaling:launchconfiguration", "OptionName": "InstanceType", "Value": "t3.small"},
{"Namespace": "aws:autoscaling:asg", "OptionName": "MinSize", "Value": "2"},
{"Namespace": "aws:autoscaling:asg", "OptionName": "MaxSize", "Value": "6"},
{"Namespace": "aws:elasticbeanstalk:environment", "OptionName": "EnvironmentType", "Value": "LoadBalanced"},
{"Namespace": "aws:elasticbeanstalk:environment", "OptionName": "LoadBalancerType", "Value": "application"},
{"Namespace": "aws:elasticbeanstalk:environment", "OptionName": "ServiceRole", "Value": "eb-orders-service"},
{"Namespace": "aws:elasticbeanstalk:command", "OptionName": "DeploymentPolicy", "Value": "Immutable"},
{"Namespace": "aws:elasticbeanstalk:healthreporting:system", "OptionName": "SystemType", "Value": "enhanced"},
{"Namespace": "aws:elasticbeanstalk:managedactions", "OptionName": "ManagedActionsEnabled", "Value": "true"},
{"Namespace": "aws:elasticbeanstalk:managedactions", "OptionName": "PreferredStartTime", "Value": "Sun:21:00"},
{"Namespace": "aws:elasticbeanstalk:managedactions:platformupdate", "OptionName": "UpdateLevel", "Value": "minor"},
{"Namespace": "aws:elasticbeanstalk:application:environment", "OptionName": "RECEIPT_BUCKET", "Value": "$RECEIPTS"},
{"Namespace": "aws:ec2:vpc", "OptionName": "VPCId", "Value": "$VPC"},
{"Namespace": "aws:ec2:vpc", "OptionName": "Subnets", "Value": "$PRIVATE_SUBNETS"},
{"Namespace": "aws:ec2:vpc", "OptionName": "ELBSubnets", "Value": "$PUBLIC_SUBNETS"},
{"Namespace": "aws:ec2:vpc", "OptionName": "AssociatePublicIpAddress", "Value": "false"},
{"Namespace": "aws:elbv2:listener:443", "OptionName": "Protocol", "Value": "HTTPS"},
{"Namespace": "aws:elbv2:listener:443", "OptionName": "SSLCertificateArns", "Value": "$CERT_ARN"}
]
EOF
aws elasticbeanstalk create-environment --region $REGION --application-name orders-api --environment-name orders-prod \
--solution-stack-name "$STACK" --version-label 1.4.2 --option-settings file://options.json
aws elasticbeanstalk wait environment-exists --region $REGION --application-name orders-api --environment-names orders-prod
aws elasticbeanstalk describe-environments --region $REGION --environment-names orders-prod \
--query 'Environments[0].{status:Status,health:Health,url:CNAME}'
# 5. Ship the next version: upload it, then point the environment at it. The immutable policy starts a fresh set of instances first.
aws elasticbeanstalk create-application-version --region $REGION --application-name orders-api --version-label 1.5.0 \
--source-bundle S3Bucket=$BUCKET,S3Key=orders-api/orders-1.5.0.zip
aws elasticbeanstalk update-environment --region $REGION --environment-name orders-prod --version-label 1.5.0
aws elasticbeanstalk wait environment-updated --region $REGION --application-name orders-api --environment-names orders-prod
# 6. Is a platform update waiting?
aws elasticbeanstalk describe-environment-managed-actions --region $REGION --environment-name orders-prod --query "ManagedActions[].{type:ActionType,status:Status,desc:ActionDescription}"
# Placeholders: pass in your own VPC, subnets, certificate and the platform name (find it with
# `aws elasticbeanstalk list-available-solution-stacks`).
variable "vpc_id" {
type = string
}
variable "private_subnets" {
type = list(string)
}
variable "public_subnets" {
type = list(string)
}
variable "certificate_arn" {
type = string
}
variable "solution_stack_name" {
type = string
}
variable "receipt_bucket" {
type = string
default = "orders-receipts-example"
}
data "aws_iam_policy_document" "eb_trust" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["elasticbeanstalk.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "ec2_trust" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "service" {
name = "eb-orders-service"
assume_role_policy = data.aws_iam_policy_document.eb_trust.json
}
resource "aws_iam_role_policy_attachment" "service" {
for_each = toset([
"service-role/AWSElasticBeanstalkEnhancedHealth",
"service-role/AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy",
])
role = aws_iam_role.service.name
policy_arn = "arn:aws:iam::aws:policy/${each.key}"
}
resource "aws_iam_role" "instance" {
name = "eb-orders-instance"
assume_role_policy = data.aws_iam_policy_document.ec2_trust.json
}
resource "aws_iam_role_policy_attachment" "web_tier" {
role = aws_iam_role.instance.name
policy_arn = "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier"
}
resource "aws_iam_role_policy" "receipts" {
name = "receipts-write"
role = aws_iam_role.instance.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "s3:PutObject"
Resource = "arn:aws:s3:::${var.receipt_bucket}/receipts/*"
}]
})
}
resource "aws_iam_instance_profile" "instance" {
name = "eb-orders-instance"
role = aws_iam_role.instance.name
}
resource "aws_elastic_beanstalk_application" "orders" {
name = "orders-api"
description = "Orders API"
}
resource "aws_elastic_beanstalk_environment" "prod" {
name = "orders-prod"
application = aws_elastic_beanstalk_application.orders.name
solution_stack_name = var.solution_stack_name
tier = "WebServer"
setting {
namespace = "aws:autoscaling:launchconfiguration"
name = "IamInstanceProfile"
value = aws_iam_instance_profile.instance.name
}
setting {
namespace = "aws:autoscaling:launchconfiguration"
name = "InstanceType"
value = "t3.small"
}
setting {
namespace = "aws:autoscaling:asg"
name = "MinSize"
value = "2"
}
setting {
namespace = "aws:autoscaling:asg"
name = "MaxSize"
value = "6"
}
setting {
namespace = "aws:elasticbeanstalk:environment"
name = "EnvironmentType"
value = "LoadBalanced"
}
setting {
namespace = "aws:elasticbeanstalk:environment"
name = "LoadBalancerType"
value = "application"
}
setting {
namespace = "aws:elasticbeanstalk:environment"
name = "ServiceRole"
value = aws_iam_role.service.name
}
setting {
namespace = "aws:elasticbeanstalk:command"
name = "DeploymentPolicy"
value = "Immutable"
}
setting {
namespace = "aws:elasticbeanstalk:healthreporting:system"
name = "SystemType"
value = "enhanced"
}
setting {
namespace = "aws:elasticbeanstalk:managedactions"
name = "ManagedActionsEnabled"
value = "true"
}
setting {
namespace = "aws:elasticbeanstalk:managedactions"
name = "PreferredStartTime"
value = "Sun:21:00"
}
setting {
namespace = "aws:elasticbeanstalk:managedactions:platformupdate"
name = "UpdateLevel"
value = "minor"
}
setting {
namespace = "aws:elasticbeanstalk:application:environment"
name = "RECEIPT_BUCKET"
value = var.receipt_bucket
}
setting {
namespace = "aws:ec2:vpc"
name = "VPCId"
value = var.vpc_id
}
setting {
namespace = "aws:ec2:vpc"
name = "Subnets"
value = join(",", var.private_subnets)
}
setting {
namespace = "aws:ec2:vpc"
name = "ELBSubnets"
value = join(",", var.public_subnets)
}
setting {
namespace = "aws:ec2:vpc"
name = "AssociatePublicIpAddress"
value = "false"
}
setting {
namespace = "aws:elbv2:listener:443"
name = "Protocol"
value = "HTTPS"
}
setting {
namespace = "aws:elbv2:listener:443"
name = "SSLCertificateArns"
value = var.certificate_arn
}
depends_on = [aws_iam_role_policy_attachment.service, aws_iam_role_policy_attachment.web_tier]
}
output "environment_url" {
value = aws_elastic_beanstalk_environment.prod.cname
}
# Deploys a version that is already in S3 and waits for the environment to settle. Usage: deploy.py <version-label>
import sys
import time
import boto3
eb = boto3.client("elasticbeanstalk")
APP, ENV = "orders-api", "orders-prod"
BUCKET = "orders-eb-versions-example"
def deploy(label):
eb.create_application_version(
ApplicationName=APP, VersionLabel=label,
SourceBundle={"S3Bucket": BUCKET, "S3Key": "orders-api/orders-%s.zip" % label},
Description="deployed by deploy.py")
started = time.time()
eb.update_environment(EnvironmentName=ENV, VersionLabel=label)
eb.get_waiter("environment_updated").wait(ApplicationName=APP, EnvironmentNames=[ENV],
WaiterConfig={"Delay": 15, "MaxAttempts": 80})
env = eb.describe_environments(EnvironmentNames=[ENV])["Environments"][0]
print("%s is %s, health %s, running %s" % (env["EnvironmentName"], env["Status"], env["Health"], env["VersionLabel"]))
if env["Health"] != "Green" or env["VersionLabel"] != label:
events = eb.describe_events(EnvironmentName=ENV, StartTime=time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(started)),
Severity="WARN")["Events"]
for e in events[:8]:
print(" %s %s" % (e["Severity"], e["Message"]))
sys.exit("deployment did not leave the environment green on %s" % label)
if __name__ == "__main__":
deploy(sys.argv[1])
// dotnet add package AWSSDK.ElasticBeanstalk
// Lists every environment with its status, health and version, and the warnings and errors from the last day.
using Amazon.ElasticBeanstalk;
using Amazon.ElasticBeanstalk.Model;
using var eb = new AmazonElasticBeanstalkClient();
var envs = (await eb.DescribeEnvironmentsAsync(new DescribeEnvironmentsRequest { IncludeDeleted = false })).Environments;
int worrying = 0;
foreach (EnvironmentDescription env in envs.OrderBy(e => e.ApplicationName).ThenBy(e => e.EnvironmentName))
{
bool ok = env.Health == EnvironmentHealth.Green;
if (!ok) worrying++;
Console.WriteLine($"{env.ApplicationName}/{env.EnvironmentName,-16} {env.Status,-10} {env.Health,-7} version={env.VersionLabel} platform={env.PlatformArn?.Split('/').Last()}");
var events = (await eb.DescribeEventsAsync(new DescribeEventsRequest
{
EnvironmentName = env.EnvironmentName,
StartTime = DateTime.UtcNow.AddDays(-1),
Severity = EventSeverity.WARN,
MaxRecords = 5
})).Events;
foreach (EventDescription e in events)
Console.WriteLine($" {e.Severity,-5} {e.EventDate:u} {e.Message}");
}
Console.WriteLine(worrying == 0 ? $"{envs.Count} environment(s), all green." : $"{worrying} of {envs.Count} environment(s) need a look.");
return worrying == 0 ? 0 : 1;
Best videos to explore
Videos picked for this service. Each one is labelled with its source, opens on YouTube if you prefer, and loads only when you press play.
Interview questions
BasicWhat is AWS Elastic Beanstalk?
It’s a service that deploys and runs web applications from your code. You upload a bundle or a Docker setup and choose a platform, and Beanstalk creates the EC2 instances, the load balancer, the Auto Scaling group and the health monitoring. The resources stay visible in your account, and you pay for them, not for Beanstalk.
BasicHow much does Elastic Beanstalk cost?
AWS charges nothing for Beanstalk itself. You pay for the underlying resources it creates: EC2 instances, the load balancer, EBS volumes, S3 storage for application versions, CloudWatch and data transfer. A load-balanced environment bills around the clock, so a small test app can still cost real money.
BasicIs Elastic Beanstalk still supported?
Yes, the service is active. AWS did retire its remaining Amazon Linux 2 platform branches on 6 August 2026 because Amazon Linux 2 reached end of life, so environments need to run on Amazon Linux 2023 platform branches. Retired branches get no maintenance updates.
IntermediateWhat are the Elastic Beanstalk deployment policies?
All at once replaces every instance together and is fastest but causes downtime. Rolling updates in batches. Rolling with additional batch keeps full capacity by adding a batch first. Immutable starts a new set of instances and swaps them in if they’re healthy, which is the safest for production. Traffic splitting sends a percentage of traffic to the new version for a canary release.
IntermediateHow do you do a blue/green deployment on Beanstalk?
Create a second environment running the new version, test it on its own URL, and then swap the CNAMEs of the two environments. Traffic moves to the new one, and the old one stays up for a quick rollback. It’s also the way to move between platform generations, such as Amazon Linux 2 to Amazon Linux 2023.
IntermediateWhy shouldn’t the production database be created inside the Beanstalk environment?
The database becomes part of the environment’s lifecycle, so terminating or rebuilding the environment deletes it and complicates upgrades. Create the database separately, for example on Amazon RDS, and give the application its address as an environment variable.
AdvancedHow would you migrate an environment from a retired Amazon Linux 2 platform branch to Amazon Linux 2023?
Create a new environment on a current branch from the same application version and saved configuration, adjusting hooks and paths that assumed the old operating system, test it, then swap CNAMEs and keep the old environment briefly for rollback. An in-place move between these generations isn’t supported, so plan the blue/green swap and check dependencies, Procfile and any .ebextensions commands.
AdvancedWhat goes wrong with heavy .ebextensions customisation?
Resource definitions in .ebextensions are merged into the CloudFormation stack that Beanstalk manages, so a mistake can break updates, and hand-edited resources drift from what the service expects. Prefer option settings and .platform hooks, keep custom commands idempotent, and avoid modifying Beanstalk-managed resources by hand.
AdvancedHow would you keep an environment secure by default?
Run instances in private subnets behind a load balancer with HTTPS, grant the instance profile only what the app needs, keep secrets in Secrets Manager or Parameter Store, turn on managed platform updates and enhanced health, add AWS WAF, disable SSH in favour of Session Manager, and send logs and health events to CloudWatch. Track platform end-of-life dates as a recurring task.
AdvancedWhen would you choose Beanstalk over containers on ECS, EKS or a serverless container service?
Beanstalk suits a conventional web app that runs well on EC2, where the team wants a quick path from code to a load-balanced environment and still wants access to the instances. Containers on ECS or EKS suit many services with consistent packaging and fine scheduling, and serverless container platforms suit spiky traffic and scale to zero. Many teams start on Beanstalk and move services out as they grow.
Similar or alternative services on other clouds
| Capability | AWS | Azure | Google Cloud |
|---|---|---|---|
| Service | AWS Elastic Beanstalk | Azure App Service | Google App Engine |
| What you upload | Zip, WAR or Docker setup | Zip, container image or source from Git | Source code with an app.yaml (or a Docker image on flexible) |
| Compute underneath | EC2 instances you can see | App Service plan, shared by apps | Sandboxed instances (standard) or VMs (flexible) |
| Scale to zero | No | No, the plan keeps running | Yes on the standard environment |
| Safe rollouts | Immutable, rolling, traffic splitting, CNAME swap | Deployment slots with swap | Versions with traffic splitting |
| Platform updates | Managed updates; old branches retire | Runtime updates by Microsoft | Runtime versions set in app.yaml, old ones deprecate |
| Cost of the service | No extra charge, pay for resources | Pay for the plan per instance-hour | Pay for instance hours, with a free daily allowance on standard |
| Direct infrastructure access | Yes, EC2 and the load balancer are in your account | Limited, with App Service Environment for isolation | Limited on standard, VMs on flexible |
For serverless code with no servers at all, look at AWS Lambda. For containers at scale use Amazon EKS, and for full control of the machine use Amazon EC2. Databases for a Beanstalk app usually live outside it on Amazon RDS, and uploaded files on Amazon S3.
Did you find this article helpful?
Your answer helps us improve this page for the next reader.
Sources and further reading
CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.
- What is AWS Elastic Beanstalk?Amazon Web Services
- Release: Elastic Beanstalk Amazon Linux 2 platform branches retired on August 6, 2026Amazon Web Services
- Deployment policies and settingsAmazon Web Services
- Configuration optionsAmazon Web Services
- Managed platform updatesAmazon Web Services
- Enhanced health reporting and monitoringAmazon Web Services
- Blue/Green deployments with Elastic BeanstalkAmazon Web Services
- AWS Elastic Beanstalk pricingAmazon Web Services
- Terraform AWS provider: aws_elastic_beanstalk_environmentHashiCorp
