How I Cut My AWS Bill From $823 to $180
AI Summary · Perspective of a Serial Entrepreneur (The following content is distilled by AI; viewpoints belong to the original author. You can skip the original article after reading this.)
The author reduced the monthly AWS bill for a production-grade SaaS system from $822.96 to an estimated $180–220, using the core logic of distinguishing “business boundaries” from “cost optimization.” Key actions included merging multiple ALBs, downsizing Fargate (keeping CPU at the minimum viable level), deleting idle Aurora Readers, and starting/stopping Staging environments on demand. This article provides a reproducible SOP for cloud cost governance, making it a valuable reference for independent developers or early-stage teams running workloads on AWS.
- Review the bill before changing architecture: break down fixed and variable costs by service…
- Merge the entry layer: share one ALB across multiple domains/environments, routing via Host Header to save on multi-instance hourly fees.
- Downsize based on monitoring data: retain a buffer of low CPU/memory (e.g., reduce API to 0.25 vCPU / 0.5 GB).
- Run Staging on demand: set desired=0 and use scripts for scheduled start/stop, which saves more than cron jobs and avoids oversight.
- Right-size the database: evaluate whether Writer/Reader separation is truly necessary…
Key Takeaway: The essence of cloud cost optimization isn’t “switching to smaller servers,” but first dissecting bills to separate fixed costs from variable costs, then precisely downsizing based on monitoring data, while preserving scaling paths. The author cut the monthly AWS bill of a real production SaaS from $822.96 to an estimated $180–220. The core strategy was consolidating entry points, right-sizing compute, and running resources on demand.
I. Bill Dissection: See Exactly Where the Money Goes
Before optimizing, split the $822.96 monthly bill by service. The high cost stemmed not from “heavy traffic” but from “multiple always-on resources”:
- Amazon ECS: $276.59 (main compute cost)
- RDS: $174.79 (database)
- EC2 – Other: $142.32 (of which NAT Gateway hourly fees + data processing fees account for $135.72)
- Elastic Load Balancing: $77.82 (mostly fixed hourly fees for multiple ALBs)
- CloudWatch: $57.10 & VPC: $41.84
Key Insight: The optimization order should be: first handle fixed resources billed by the hour (NAT, ALB, Fargate), then address small variable costs tied to usage volume.
II. Five Practical Actions (With Specific Data)
1. Merge ALBs to Share the Entry Layer
Production and Staging originally had multiple ALBs each. At low load, fixed hourly fees exceeded traffic-based costs. The optimization plan:
- Action: Keep only one shared ALB per environment, routing Dashboard, Gateway, OpenAPI, and SuperAdmin traffic to their respective Target Groups via Host Header and Path Rules.
- Risk Control: Create new rules and verify health checks first. Only modify DNS after confirmation. Retain old ALBs as fallback until verification is complete. Never delete an ALB just because its status shows Active; you must check Listener Rule hit counts and DNS pointers.
2. Guide Fargate Downsizing With Monitoring Data
Don’t shrink based on intuition; look at 24-hour monitoring data. Before optimization, average CPU for API/Web was only 2.6% / 2.36%, with peaks under 6%.
- Action: Reduce API and Web to 0.25 vCPU / 0.5 GB (OpenAPI/SuperAdmin were already at minimum specs). Perform rolling updates via ECS: start new tasks → verify health checks → drain old tasks.
- Result: After downsizing, average CPU rose to 4.84%/5.34% with peaks of 12.88%/17.28%; memory peaks remained below 7%. Running 4 minimum-spec tasks in production lowered monthly Fargate costs to approximately $36.
- Scale-Up Readiness: Set idle Workers to desired=0 rather than deleting them. This allows rapid scaling later by simply increasing the desired count or adjusting the Task Definition.
3. Delete Database Readers on Demand
Writers handle writes and transactions; Readers分担 read queries and take over during failures. Optimization criteria:
- Verification: Confirm the Reader is not idle (i.e., it was handling business reads) but that the Writer can handle all reads under current load.
- Action: Switch connections back to the Writer, perform a rolling app restart, check
pg_stat_activityto confirm no business connections remain, then delete the Reader. - Cost Savings: Save approximately $43.20–44.64 per month. Keep a Serverless v2 Writer with minimum capacity of 0.5 ACU in production.
- Terraform Note: Use
for_eachinstead ofcount, and use amovedblock to preserve the Writer’s resource identity, avoiding false replacement detection in Plan outputs.
4. Run Staging Environments Truly on Demand
Scheduled start/stop is prone to oversight. Management via scripts is recommended:
- Action: Disable auto-start. Set all four Staging ECS services to desired=0 and Aurora’s minimum capacity to 0 ACU (auto-pauses after 15 minutes of idleness).
- Execution: Write a unified script
staging-on-demand.shcovering start/status/stop. Run a full recovery drill first (start → health check → stop). Only put it into daily use after proving it can reliably bring services up.
5. Verify Dependencies Before Deleting NAT Gateways
NAT gateway hourly fees are ~$77.38 per unit plus data processing costs. Before optimization, two NATs were consuming significant fixed costs. Before deletion, prove the system doesn’t rely on public internet egress (e.g., uses only internal communication or VPC Endpoints). Otherwise, evaluate carefully.
III. Pitfall Guide
- Don’t chase the cheapest single instance: While it saves money, it creates a single point of failure and changes the deployment workflow, sacrificing future scaling flexibility.
- Downsizing isn’t deleting replicas: After Fargate downsizing, a single task isn’t highly available. ECS will auto-recreate it, but there’s a brief downtime window. If load or SLA requirements increase, the first action should be restoring replica counts for critical services.
- Always have a rollback path before any deletion: Keep old ALBs and old Readers until the new configuration proves stable, ensuring you can immediately roll back if issues arise.
IV. Reproducible Steps Summary
- Check the bill: Break down by service to identify major fixed-cost drivers (NAT, ALB, always-on compute).
- Define boundaries: Clarify that Production cannot tolerate interruption, while Staging can accept startup delays.
- Consolidate entry points: Merge multiple ALBs into one, routing via Host/Path rules.
- Downsize based on monitoring: Reduce Fargate specs using 24h monitoring data, while preserving rolling update capability.
- Evaluate the database: Confirm Reader necessity, safely switch traffic, delete it, and maintain Terraform state consistency.
- Scriptize Staging: Use desired=0 + automated start/stop scripts instead of manual or cron-based management.
- Validate via rolling changes: Change one component at a time; verify health before proceeding to the next step.
Final Result: Monthly costs dropped from $822.96 to an estimated $180–220, a reduction of approximately 73%, while preserving rapid scaling paths and production stability.
Original article · Jake blog: Read original article →
Related tool recommendation (promotion): Qiniu Cloud Lite Cloud Server Promotion