Elastic Beanstalk
Elastic Beanstalk is a PaaS that handles capacity provisioning, load balancing, auto-scaling and health monitoring. It is a good fit when the team wants to own the application and not the orchestration layer.
The standard. Using AWS Elastic Beanstalk as an orchestration platform for web applications — capacity provisioning, load balancing, auto-scaling and health monitoring — and knowing when it is the wrong choice.
When to use it
| Use Elastic Beanstalk when | Use containers or serverless when |
|---|---|
| The application is a conventional web service in a supported platform | The team needs full control of the runtime or OS |
| The team wants managed capacity and scaling without cluster operations | The workload is event-driven and intermittent |
| Deployment is application-artefact based (zip, war, Docker image) | The workload has complex orchestration or many services |
| Time to production matters more than infrastructure control | Custom networking, sidecars or service mesh are required |
Alternatives are considered explicitly — Heroku, App Runner, ECS Fargate — and the reason for the choice is recorded. Elastic Beanstalk is usually selected where the team's skills and the application's shape align with a platform abstraction.
Environment setup
Platform
- Managed platform matching the runtime, updated automatically within an approved maintenance window.
- Platform version pinned for production; upgrades tested in staging first.
- Custom platforms and Docker environments used only where the managed platform cannot meet a requirement.
IAM
| Role | Purpose | Scope |
|---|---|---|
| Service role | Allows Elastic Beanstalk to manage resources | AWS-managed AWSElasticBeanstalkService plus the specific resources it needs |
| EC2 instance profile | Allows instances to access S3, CloudWatch, SSM, Secrets Manager | Least privilege for the application's actual needs |
| Environment-specific roles | Isolates dev, staging and production | Separate roles per environment |
AWSElasticBeanstalkFullAccess is not attached to workload roles. It is an
administrative policy, not an application one.
Network
- Custom VPC with private subnets for instances and public subnets for the load balancer.
- Security groups: load balancer accepts 443 from the internet; instances accept traffic only from the load balancer; database accepts traffic only from instances.
- VPC endpoints for S3, CloudWatch Logs and Secrets Manager, so instance traffic does not traverse the internet.
- Single-instance environments only for development.
Application structure
myapp/
├── .ebextensions/
│ ├── 01-environment.config
│ ├── 02-logging.config
│ └── 03-security.config
├── .platform/
│ └── hooks/
│ ├── prebuild/
│ └── postdeploy/
├── src/
├── package.json
└── README.md
EB Extensions
# .ebextensions/02-logging.config
option_settings:
aws:elasticbeanstalk:cloudwatch:logs:
StreamLogs: true
DeleteOnTerminate: false
RetentionInDays: 30
aws:elasticbeanstalk:cloudwatch:logs:health:
HealthStreamingEnabled: true
RetentionInDays: 7
files:
"/etc/awslogs/config/app.conf":
mode: "000644"
owner: root
group: root
content: |
[/var/log/app/*.log]
file = /var/log/app/*.log
log_group_name = /aws/elasticbeanstalk/`{"Ref" : "AWSEBEnvironmentName"}`/app
log_stream_name = {instance_id}
Configuration lives in .ebextensions, not in console settings. A console change
is drift and is reverted at the next deployment.
Deployment
Deployments are triggered by the pipeline, not by the console.
# Build the artefact
eb init --platform node.js --region us-east-1
eb use example-prod
# Deploy a versioned artefact
eb deploy --label "v1.4.0-${GIT_SHA}" --staged
Deployment policy
| Environment | Policy |
|---|---|
| Development | All at once |
| Staging | Rolling |
| Production | Immutable or blue/green |
An immutable deployment launches a fresh set of instances, health-checks them, then swaps them in. Rollback re-points to the previous version, which remains available in the application versions list.
Health checks
- Enhanced health reporting enabled.
- HTTP health check on an application endpoint, not just TCP.
- Health check grace period long enough for the application to start.
- Ignore thresholds configured so a single transient failure does not replace an instance.
Scaling
# .ebextensions/01-environment.config
option_settings:
aws:autoscaling:asg:
MinSize: 2
MaxSize: 8
aws:autoscaling:trigger:
MeasureName: CPUUtilization
Statistic: Average
Unit: Percent
UpperThreshold: 65
LowerThreshold: 30
aws:autoscaling:updatepolicy:rollingupdate:
RollingUpdateEnabled: true
RollingUpdateType: Health
MinInstancesInService: 2
MaxBatchSize: 1
PauseTime: PT5M
- Minimum of two instances across two Availability Zones for production.
- Scheduled scaling for predictable peaks — exam windows, business hours, batch periods.
- Target-tracking or step scaling based on the metric that actually predicts load for this workload.
- Scale-down cooldown long enough to avoid oscillation.
Monitoring
| Signal | Source | Alarm |
|---|---|---|
| Environment health | Enhanced health | Yellow for 5 min, red for 1 min |
| CPU utilisation | CloudWatch | Above 80% for 10 min |
| Latency (p95) | Load balancer | Above target for 5 min |
| 5xx rate | Load balancer | Above 1% for 3 min |
| Disk space | CloudWatch agent | Below 20% |
| Application errors | Log metric filter | Above threshold |
| Deployment failure | Elastic Beanstalk events | Any failure |
See Monitoring metrics for the metric set by tier.
Rollback
- Application rollback. Select the previous application version and deploy. Fastest and most common.
- Configuration rollback. Revert the
.ebextensionschange and redeploy. - Platform rollback. Revert to the previous platform version where an upgrade caused the fault.
Every rollback is followed by a post-incident review and a decision about whether to fix forward or re-attempt.
Best practices
- Configuration in
.ebextensions, versioned with the application. - Immutable or blue/green deployment in production.
- Enhanced health checking, with alarms on environment health.
- Log streaming to CloudWatch; no reliance on instance-local logs.
- Managed platform updates within a maintenance window.
- One environment per stage, with identical configuration apart from size.
- Database outside the environment — an RDS instance created by Elastic Beanstalk is tied to the environment's lifecycle, which makes replacement destructive.