This hands-on workshop demonstrates horizontal scaling using AWS ECS Fargate, Application Load Balancer, and autoscaling. Students will deploy a microservices architecture, configure load balancing, implement CPU-based autoscaling, and observe scaling behavior under load.
- Deploy containerized microservices using AWS CDK (Infrastructure as Code)
- Configure Application Load Balancers for traffic distribution
- Implement CPU-based autoscaling policies
- Monitor and observe scaling behavior with CloudWatch
- Perform load testing to trigger autoscaling events
- Understand horizontal scaling patterns and best practices
graph TB
%% Traffic flow
User("Users") --> ALB(["Application Load Balancer"])
ALB --> Frontend["Frontend Service<br>Ruby on Rails"]
Frontend --> NodeJS["NodeJS Service<br>Backend API"]
Frontend --> Crystal["Crystal Service<br>Backend API"]
%% ECS services
subgraph ecs_cluster ["ECS Cluster"]
direction TB
Frontend
NodeJS
Crystal
end
%% Autoscaling feedback loop
subgraph auto_scaling ["Auto Scaling"]
direction TB
ASG{{"Auto Scaling Group"}}
CW[["CloudWatch Metrics"]]
ASG -.->|"Monitors"| Frontend
CW -.->|"Triggers"| ASG
end
- AWS Account with appropriate permissions
- AWS CLI configured with credentials
- Python 3.9+
- Node.js 14+
- Docker (optional, for local testing)
- Basic understanding of containers and AWS services
This workshop is organized into phases:
- Prerequisites and Setup - Environment configuration
- Platform Infrastructure - VPC, ECS Cluster, networking
- Frontend Deployment - Deploy the main application
- Backend Services - Deploy supporting microservices
- Manual Scaling - Scale services manually
- Autoscaling - Configure and test automatic scaling
- Load Testing - Trigger scaling events
- Cleanup - Remove all resources
# Clone the repository
git clone https://github.com/gamaware/system-design-course.git
cd system-design-course/01-introduction-horizontal-scalability
# Run quick start script
chmod +x quick-start.sh
./quick-start.shFollow the detailed guides:
- STEP_BY_STEP_WORKSHOP.md - Complete walkthrough
- COMPLETE_WORKSHOP_GUIDE.md - Comprehensive guide
- WORKSHOP_GUIDE.md - Original workshop guide
- Purpose: Main web interface
- Technology: Ruby on Rails
- Port: 3000
- Scaling: Horizontal with ALB
- Purpose: Backend API service
- Technology: Node.js/Express
- Port: 3000
- Features: Service discovery integration
- Purpose: High-performance backend API
- Technology: Crystal language
- Port: 3000
- Features: Low latency responses
- Python-based CDK stacks
- Reproducible deployments
- Version-controlled infrastructure
- Easy teardown and recreation
- ECS Fargate for serverless containers
- Application Load Balancer for traffic distribution
- Target tracking autoscaling policies
- CloudWatch metrics integration
- CloudWatch Logs for application logs
- CloudWatch Metrics for performance monitoring
- Service discovery for microservices communication
- Real-time scaling visualization
# Activate workshop environment
source activate.sh
# Configure AWS credentials
aws configure
# Bootstrap CDK
cdk bootstrapcd ecsdemo-platform/cdk
cdk deploy --require-approval neverCreates:
- VPC with public/private subnets
- ECS Cluster
- Security Groups
- Service Discovery namespace
- Bastion host (optional)
cd ../../ecsdemo-frontend/cdk
cdk deploy --require-approval neverCreates:
- Application Load Balancer
- ECS Service with Fargate tasks
- Target Group
- CloudWatch Log Group
# Deploy NodeJS service
cd ../../ecsdemo-nodejs/cdk
cdk deploy --require-approval never
# Deploy Crystal service
cd ../../ecsdemo-crystal/cdk
cdk deploy --require-approval never# Scale frontend to 3 tasks
aws ecs update-service \
--cluster container-demo \
--service ecsdemo-frontend \
--desired-count 3
# Verify scaling
aws ecs describe-services \
--cluster container-demo \
--services ecsdemo-frontend \
--query 'services[0].desiredCount'# Register scalable target
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/container-demo/ecsdemo-frontend \
--min-capacity 1 \
--max-capacity 10
# Create scaling policy
aws application-autoscaling put-scaling-policy \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/container-demo/ecsdemo-frontend \
--policy-name cpu-scaling-policy \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration \
'{"TargetValue":50.0,"PredefinedMetricSpecification":{"PredefinedMetricType":"ECSServiceAverageCPUUtilization"},"ScaleInCooldown":30,"ScaleOutCooldown":30}'# Get ALB URL
ALB_URL=$(aws elbv2 describe-load-balancers \
--query 'LoadBalancers[0].DNSName' \
--output text)
# Run load test with siege
siege -c 200 -t 2m http://$ALB_URL
# Monitor scaling in real-time
watch -n 5 'aws ecs describe-services \
--cluster container-demo \
--services ecsdemo-frontend \
--query "services[0].desiredCount"'# View CPU utilization
aws cloudwatch get-metric-statistics \
--namespace AWS/ECS \
--metric-name CPUUtilization \
--dimensions Name=ServiceName,Value=ecsdemo-frontend \
--start-time $(date -u -d '10 minutes ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 60 \
--statistics Average# Stream logs from frontend service
awslogs get /ecs/ecsdemo-frontend --watch# Check service status
aws ecs describe-services \
--cluster container-demo \
--services ecsdemo-frontend ecsdemo-nodejs ecsdemo-crystalTarget: 50% CPU utilization Scale Out: Add tasks when CPU > 50% Scale In: Remove tasks when CPU < 50% Cooldown: 30 seconds
Target: 80% memory utilization Scale Out: Add tasks when memory > 80% Scale In: Remove tasks when memory < 80%
# Check service events
aws ecs describe-services \
--cluster container-demo \
--services ecsdemo-frontend \
--query 'services[0].events[0:5]'
# Check task status
aws ecs list-tasks \
--cluster container-demo \
--service-name ecsdemo-frontend
# View task logs
aws logs tail /ecs/ecsdemo-frontend --follow# Check target health
aws elbv2 describe-target-health \
--target-group-arn <target-group-arn>
# Check ALB listeners
aws elbv2 describe-listeners \
--load-balancer-arn <alb-arn># Check scaling policies
aws application-autoscaling describe-scaling-policies \
--service-namespace ecs
# Check scaling activities
aws application-autoscaling describe-scaling-activities \
--service-namespace ecs \
--resource-id service/container-demo/ecsdemo-frontend# Delete services in reverse order
cd ecsdemo-crystal/cdk && cdk destroy --force
cd ../../ecsdemo-nodejs/cdk && cdk destroy --force
cd ../../ecsdemo-frontend/cdk && cdk destroy --force
cd ../../ecsdemo-platform/cdk && cdk destroy --force
# Deactivate environment
source deactivate.shEstimated costs for running this workshop:
- ECS Fargate tasks: ~$0.04/hour per task
- Application Load Balancer: ~$0.025/hour
- NAT Gateway: ~$0.045/hour
- Data transfer: Minimal for testing
Total estimated cost: ~$0.50-$1.00 per hour
💡 Tip: Always run cleanup after completing the workshop to avoid unnecessary charges.
- Adding more instances of the same service
- Distributes load across multiple containers
- Increases availability and fault tolerance
- Scales based on demand
- Increasing resources (CPU/memory) of existing instances
- Limited by instance size constraints
- Requires downtime for changes
- Target Tracking: Maintain specific metric target
- Step Scaling: Scale based on metric thresholds
- Scheduled Scaling: Scale at specific times
- Round Robin: Distribute requests evenly
- Least Outstanding Requests: Send to least busy target
- Health Checks: Remove unhealthy targets automatically
- STEP_BY_STEP_WORKSHOP.md - Detailed step-by-step instructions
- COMPLETE_WORKSHOP_GUIDE.md - Comprehensive guide with explanations
- WORKSHOP_GUIDE.md - Original workshop documentation
Created by Alex Garcia
This project is licensed under the MIT License - see the LICENSE file for details.