Introduction to Cost Optimization for Elastic Beanstalk
AWS Elastic Beanstalk is a Platform-as-a-Service (PaaS) that automates the deployment and scaling of web applications. While it simplifies infrastructure management, it can also lead to unexpected costs if not configured carefully. Cost optimization for Elastic Beanstalk involves selecting the right resources, configuring auto-scaling wisely, leveraging pricing models, and eliminating wasteβall without sacrificing performance or reliability.
Why Cost Optimization Matters
Unoptimized Elastic Beanstalk environments can accumulate charges from EC2 instances, load balancers, data transfer, and additional services like RDS or ElastiCache. Without proactive optimization, you may pay for:
- Over-provisioned instance types that sit idle
- Multiple environments (e.g., staging, testing) left running 24/7
- Unused load balancer capacity
- Auto-scaling policies that react too slowly or too aggressively
By implementing cost optimization strategies, you can reduce your monthly bill by 30β60% while maintaining the same user experience.
Key Strategies and How to Use Them
Below are practical, actionable techniques to optimize costs in Elastic Beanstalk, each accompanied by code examples and configuration snippets.
1. Right-Sizing Instance Types
Choose instance families that match your workload. For burstable workloads (low CPU most of the time with occasional spikes), use t3 or t4g instances. For memory-intensive apps, r5 or r6g; for compute-intensive, c5 or c6g. Use the Elastic Beanstalk console or a .ebextensions config file to set the instance type.
# .ebextensions/instance-type.config
option_settings:
aws:autoscaling:launchconfiguration:
InstanceType: "t3.small"
2. Use Spot Instances (with a Fallback)
Spot Instances can reduce EC2 costs by up to 90%. Elastic Beanstalk supports mixed instances with a combination of On-Demand and Spot. Configure a launch template or use an .ebextensions file with a custom launch configuration.
# .ebextensions/spot-instances.config
option_settings:
aws:autoscaling:launchconfiguration:
InstanceType: "c5.large"
SpotPrice: "0.05" # Optional: your max bid
IamInstanceProfile: "aws-elasticbeanstalk-ec2-role"
For better resilience, use a mixed instances policy via a CloudFormation template or the EB CLI. Example using eb extend with a saved configuration:
# save as .ebextensions/mixed-instances.config
Resources:
AWSEBAutoScalingLaunchConfiguration:
Type: "AWS::AutoScaling::LaunchConfiguration"
Properties:
InstanceType: "t3.medium"
SpotPrice: ""
ImageId: "ami-0abcdef1234567890"
IamInstanceProfile: "aws-elasticbeanstalk-ec2-role"
3. Implement Scheduled Scaling for Non-Production Environments
Turn off or scale down environments during off-hours. Use the AWS Auto Scaling scheduled actions. Create a .ebextensions file to define a schedule that reduces the minimum and desired capacity to 0 (or 1) at night and restores it in the morning.
# .ebextensions/scheduled-scaling.config
Resources:
ScaleDownSchedule:
Type: "AWS::AutoScaling::ScheduledAction"
Properties:
AutoScalingGroupName: !Ref "AWSEBAutoScalingGroup"
Recurrence: "0 22 * * *" # 10 PM UTC every day
MinSize: "0"
DesiredCapacity: "0"
MaxSize: "0"
ScaleUpSchedule:
Type: "AWS::AutoScaling::ScheduledAction"
Properties:
AutoScalingGroupName: !Ref "AWSEBAutoScalingGroup"
Recurrence: "0 7 * * *" # 7 AM UTC every day
MinSize: "1"
DesiredCapacity: "1"
MaxSize: "4"
4. Optimize Auto-Scaling Thresholds
Set conservative scaling policies to avoid unnecessary instance launches. Use CPU utilization or request count as metrics, and add cooldown periods. Example using a custom configuration file:
# .ebextensions/scaling-policies.config
option_settings:
aws:autoscaling:asg:
MinSize: "1"
MaxSize: "4"
aws:autoscaling:trigger:
LowerThreshold: "30"
UpperThreshold: "70"
MeasureName: "CPUUtilization"
Statistic: "Average"
Unit: "Percent"
Period: "300" # 5 minutes
BreachDuration: "2" # number of periods before scaling
UpperBreachScaleIncrement: "1"
LowerBreachScaleIncrement: "-1"
5. Use Elastic Load Balancer Wisely
If your application can tolerate a single point of failure (e.g., development), choose a single-instance environment without a load balancer. For production, use an Application Load Balancer (ALB) instead of a Classic Load Balancer (CLB) because ALB supports path-based routing and is more cost-effective at scale. Set idle timeout and disable cross-zone load balancing if not needed.
# .ebextensions/lb-settings.config
option_settings:
aws:elb:loadbalancer:
CrossZone: "false"
IdleTimeout: "60"
6. Leverage Reserved Instances for Steady Workloads
For environments that run 24/7 (e.g., production), purchase Reserved Instances (RIs) for the instance family you use. Elastic Beanstalk does not directly manage RIs, but you can apply them to your EC2 instances. Use the AWS Cost Explorer to identify your baseline usage, then buy Standard or Convertible RIs for a 1- or 3-year term.
7. Terminate Idle Environments
Developers often forget to stop temporary environments. Use the Elastic Beanstalk CLI to programmatically terminate environments after a certain period. Example script using the AWS CLI and a cron job:
#!/bin/bash
# terminate-idle-envs.sh
# List environments older than 7 days (adjust tag logic as needed)
aws elasticbeanstalk describe-environments --query "Environments[?Status=='Ready'].[EnvironmentName, DateCreated]" --output text | while read name created; do
created_epoch=$(date -d "$created" +%s)
now_epoch=$(date +%s)
age_days=$(( (now_epoch - created_epoch) / 86400 ))
if [ $age_days -gt 7 ]; then
echo "Terminating environment $name (age $age_days days)"
aws elasticbeanstalk terminate-environment --environment-name "$name"
fi
done
Add this to a cron job (0 0 * * 0 weekly) or use AWS Lambda with a CloudWatch Events rule.
8. Enable Detailed CloudWatch Monitoring Selectively
Basic monitoring (5-minute intervals) is free. Detailed monitoring (1-minute) costs extra per instance. Only enable it for critical environments. Disable it in configuration:
# .ebextensions/monitoring.config
option_settings:
aws:autoscaling:launchconfiguration:
EnableDetailedMonitoring: "false"
Best Practices
- Use the "Saved Configurations" feature: Create a base cost-optimized configuration (e.g.,
cost-optimized-prod.cfg) and reuse it for new environments. This ensures consistency. - Tag environments for cost allocation: Add tags like
Environment:production,CostCenter:engineeringto track spending per team or project. - Set budget alerts: Use AWS Budgets to receive notifications when costs exceed a threshold (e.g., $100/month).
- Regularly review usage: Use AWS Cost Explorer to find underutilized instances (low CPU, high memory waste). Switch to smaller instance types or burstable families.
- Combine with other AWS services: Use ElastiCache for caching (reduce database load) and CloudFront for content delivery (reduce EC2 traffic).
- Enable termination protection on production environments: Prevent accidental deletion but still enforce cost controls via scheduled scaling.
- Use Elastic Beanstalk's "swap environment URLs" for blue/green deployments: Instead of running two full environments, use the same environment for the swap, reducing costs.
- Consider Graviton-based instances:
t4g,c6g,m6ginstances offer better price/performance for ARM-compatible applications.
Putting It All Together: A Cost-Optimized .ebextensions Example
# .ebextensions/cost-optimization.config
option_settings:
aws:autoscaling:launchconfiguration:
InstanceType: "t3.small"
IamInstanceProfile: "aws-elasticbeanstalk-ec2-role"
EnableDetailedMonitoring: "false"
aws:autoscaling:asg:
MinSize: "1"
MaxSize: "3"
aws:autoscaling:trigger:
LowerThreshold: "30"
UpperThreshold: "70"
MeasureName: "CPUUtilization"
Statistic: "Average"
Unit: "Percent"
Period: "300"
BreachDuration: "2"
UpperBreachScaleIncrement: "1"
LowerBreachScaleIncrement: "-1"
aws:elb:loadbalancer:
CrossZone: "false"
IdleTimeout: "60"
Resources:
ScaleDownSchedule:
Type: "AWS::AutoScaling::ScheduledAction"
Properties:
AutoScalingGroupName: !Ref "AWSEBAutoScalingGroup"
Recurrence: "0 22 * * *"
MinSize: "0"
DesiredCapacity: "0"
MaxSize: "0"
ScaleUpSchedule:
Type: "AWS::AutoScaling::ScheduledAction"
Properties:
AutoScalingGroupName: !Ref "AWSEBAutoScalingGroup"
Recurrence: "0 7 * * *"
MinSize: "1"
DesiredCapacity: "1"
MaxSize: "3"
Deploy this configuration file into your Elastic Beanstalk environment's .ebextensions/ folder. It will apply the settings on the next deployment.
Monitoring and Continuous Optimization
After implementing the above strategies, monitor your costs using the AWS Cost Explorer. Create a custom report for Elastic Beanstalk resources (EC2, ELB, EBS, etc.). Set up a monthly review to adjust instance sizes, scaling policies, and reserved instance coverage. Use the AWS Trusted Advisor for real-time cost optimization recommendations.
Conclusion
Cost optimization for AWS Elastic Beanstalk is not a one-time task but an ongoing process of right-sizing, scheduling, and leveraging pricing models. By choosing appropriate instance types, using Spot Instances, implementing scheduled scaling, optimizing auto-scaling thresholds, and eliminating idle environments, you can significantly reduce your AWS bill without compromising application performance. The practical code examples and best practices provided in this tutorial give you a solid foundation to start optimizing your Elastic Beanstalk environments today. Always test changes in a non-production environment first, and regularly revisit your cost strategy as your application evolves.