6. Cost optimisation
AWS bills get out of control fast. Tagging, cost-allocation reports, budget alerts, and savings plans make the spend visible and manageable.
The AWS bill for this deployment is the sum of a handful of per-hour and per-GB charges. The page below works through the numbers service by service so you can see where the spend actually goes, then names the highest-leverage knobs (log retention, ECR lifecycle, billing alarms) and the tagging discipline that lets the finance side ask "what does the news API cost this month?" and get a real answer.
The AWS Free Tier covers most of this deployment for the first 12 months: 750 hours/month of RDS db.t3.micro, 20 GB of RDS storage, 750 hours of ElastiCache cache.t3.micro, plus generous CloudWatch and ECR allowances. ECS Fargate is not in the Free Tier; that's the line item that exists from day one regardless.
Service-by-service cost analysis
Understanding costs requires breaking down each AWS service you're using. Here's the realistic cost analysis for your News API infrastructure:
ECS Fargate (Compute):
Charged per vCPU-hour and per GB-memory-hour. With the chapter's allocation of 0.25 vCPU + 512 MB per task and 2 tasks running continuously, the bill covers 0.5 vCPU and 1 GB. At us-east-1 pricing ($0.04048 per vCPU-hour, $0.004445 per GB-hour), that's (0.5 × $0.04048 × 730) + (1 × $0.004445 × 730) = $14.77 + $3.24 = ~$18/month for the baseline. Auto-scaling adds proportional cost only while extra tasks are running.
RDS PostgreSQL:
db.t3.micro instances (1 vCPU, 1GB memory) cost $0.017 per hour = ~$12.41/month. First 750 hours free for 12 months. Add 20GB storage at $0.115 per GB-month = $2.30/month (free first 20GB for 12 months). Add automated backups = free for storage equal to DB size. Single-AZ deployment = ~$15/month after Free Tier expires, $2.30/month during first year.
ElastiCache Redis:
cache.t3.micro nodes (1 vCPU, 0.5GB memory) cost $0.017 per hour = ~$12.41/month. First 750 hours free for 12 months. Single-node deployment = ~$12.41/month after Free Tier, $0/month during first year.
Application Load Balancer:
$0.0225 per hour = ~$16.40/month plus Load Balancer Capacity Units (LCUs). LCUs measure new connections, active connections, processed bytes, and rule evaluations. Light traffic: ~5 LCUs = ~$7.50/month. Total ALB cost: ~$24/month.
ECR (Container Registry):
$0.10 per GB-month storage. Docker images typically 500MB-2GB. With 3-4 image versions stored: ~$0.20-$0.50/month.
CloudWatch Logs:
$0.50 per GB ingested, $0.03 per GB-month storage. Application logging 100MB/day = 3GB/month ingested = $1.50/month. Stored logs with 7-day retention = ~$1/month storage. Total: ~$2.50/month.
Total Monthly Cost Estimate:
- During Free Tier (first 12 months): ECS Fargate $18 + ALB $24 + RDS $2.30 + ElastiCache $0 + ECR $0.50 + CloudWatch $2.50 = ~$47/month
- After Free Tier: ECS Fargate $18 + ALB $24 + RDS $15 + ElastiCache $12.41 + ECR $0.50 + CloudWatch $2.50 = ~$72/month
With auto-scaling, these costs increase during high-traffic periods but remain manageable. Scaling from 2 to 10 tasks for 2 hours per day adds ~$10/month in Fargate costs, worthwhile for improved user experience during peaks.
Cost optimisation strategies
Several strategies reduce AWS costs without compromising functionality or reliability:
Right-size resources:
Look at actual utilisation, then adjust. A container averaging 20% CPU at 0.25 vCPU is sized about right; averaging 10% means the allocation could come down a step. RDS at 10% CPU and 30% memory on a db.t3.micro is sized about right too. Over-provisioning wastes money; under-provisioning costs latency. The signal to look at is "average utilisation over a week of real traffic," not the peak from one load test.
Aggressive log retention:
CloudWatch log groups default to "never expire," which means the storage line on the bill grows forever even at modest log volume. Set retention to match how far back you actually search: 7 days for debug logs (if you didn't catch the problem in a week, more time on disk won't help), 30 days for application logs, 90 days for anything touching compliance. Capping retention at the right value cuts the storage component to a fraction of itself over the lifetime of the deployment.
aws logs put-retention-policy \
--log-group-name /ecs/news-api \
--retention-in-days 7
# Logs older than 7 days automatically deleted
Auto-scaling cost analysis:
Let's calculate exactly how much auto-scaling saves compared to fixed capacity:
Scenario: Your API has baseline traffic requiring 2 tasks, peak traffic requiring 8 tasks, and peaks occur 4 hours per day.
Fixed Capacity at Peak (8 tasks continuously):
8 tasks × 0.25 vCPU × $0.04048/vCPU-hour × 730 hours = $59.10
8 tasks × 0.5 GB × $0.004445/GB-hour × 730 hours = $12.98
Total: $72.08/month
Fixed Capacity at Baseline (2 tasks continuously):
2 tasks × 0.25 vCPU × $0.04048/vCPU-hour × 730 hours = $14.77
2 tasks × 0.5 GB × $0.004445/GB-hour × 730 hours = $3.24
Total: $17.01/month
Auto-Scaling (2 baseline, 8 peak for 4 hours/day):
Baseline: 2 tasks × 24 hours × 30 days = 1,440 task-hours
Peak extra: 6 tasks × 4 hours × 30 days = 720 task-hours
Total task-hours: 2,160 (versus 5,840 for fixed 8 tasks)
2,160 task-hours × 0.25 vCPU × $0.04048 = $21.86
2,160 task-hours × 0.5 GB × $0.004445 = $4.80
Total: $26.66/month
Savings Analysis:
Auto-scaling vs fixed peak: Save $45.42/month (63% reduction)
Auto-scaling vs fixed baseline: Additional $9.65/month (57% increase for peak capacity)
Key insight: Auto-scaling gives you 4× peak capacity for only 57% more than baseline cost. Fixed peak capacity would cost 4.2× baseline cost. Auto-scaling provides the best of both worlds: baseline costs most of the time, peak capacity when needed.
These calculations use actual AWS Fargate pricing as of late 2024 in us-east-1. Your costs may vary based on region, task size, and traffic patterns. The fundamental economics remain: auto-scaling reduces costs by 40-65% compared to provisioning for peak load continuously.
Clean up unused resources:
Old Docker images in ECR, orphaned security groups, terminated RDS snapshots, unused Elastic IPs, these all incur charges. Periodically audit your AWS resources and delete anything no longer needed. Set up lifecycle policies for automated cleanup:
{
"rules": [
{
"rulePriority": 1,
"description": "Keep last 10 images",
"selection": {
"tagStatus": "any",
"countType": "imageCountMoreThan",
"countNumber": 10
},
"action": {
"type": "expire"
}
}
]
}
This policy automatically deletes Docker images beyond the 10 most recent, preventing ECR storage costs from growing indefinitely.
Reserve capacity for predictable workloads:
If your application runs 24/7 for months, Reserved Instances or Savings Plans reduce costs by 30-50% compared to on-demand pricing. You commit to using specific resources for 1-3 years in exchange for discounted rates. This works well for RDS and ElastiCache (always running), less well for ECS Fargate with auto-scaling (variable usage). Analyze usage patterns before committing, reserved capacity makes sense only if you'll actually use it.
Setting up cost monitoring
AWS Cost Explorer provides visibility into your spending. Enable it to track costs over time, identify expensive services, and forecast future spending.
Create a billing alarm:
Get notified when spending exceeds thresholds:
# Create SNS topic for billing alerts
aws sns create-topic --name billing-alerts --region us-east-1
# Subscribe your email to the topic
aws sns subscribe \
--topic-arn arn:aws:sns:us-east-1:ACCOUNT_ID:billing-alerts \
--protocol email \
--notification-endpoint your-email@example.com \
--region us-east-1
# Create alarm triggering at $75/month
aws cloudwatch put-metric-alarm \
--alarm-name MonthlyBillingOver75 \
--alarm-description "Alert when monthly bill exceeds $75" \
--metric-name EstimatedCharges \
--namespace AWS/Billing \
--statistic Maximum \
--period 21600 \
--evaluation-periods 1 \
--threshold 75 \
--comparison-operator GreaterThanThreshold \
--dimensions Name=Currency,Value=USD \
--alarm-actions arn:aws:sns:us-east-1:ACCOUNT_ID:billing-alerts \
--region us-east-1
A billing alarm gives you a chance to notice cost spikes mid-month rather than at the end. If you expect $50 and an alarm at $75 fires, the investigation usually lands on one of three things: auto-scaling stayed scaled out longer than you thought, a test resource wasn't deleted, or Free Tier just expired. Catching any of those mid-month is much better than seeing them on the bill three weeks later.
Tag every resource with at least Environment and Project at creation time (--tags Key=Environment,Value=Production Key=Project,Value=NewsAPI). Cost Explorer can filter and group by tag, which is what lets you answer questions like "what does dev cost us?" or "how much of the RDS spend is the news API specifically?" Without tags, the bill is one undifferentiated number.
Next, in section 7, we look at deployment patterns beyond the default rolling update: blue-green for instant cutover, canary for gradual rollout, and ECS deployment circuit breakers that roll back automatically when a deploy's health checks don't recover.