A B2B SaaS client came to us in October 2025 with an AWS bill that had crept from $4k to $14k a month over eighteen months. Their CFO asked the obvious question: "What are we actually paying for?" Nobody on the team had a great answer. Here's how we got it down to $5.6k a month over the following ten weeks.
The starting picture
The client ran a typical mid-sized SaaS: ~3,000 active customers, ~50k MAU, multi-tenant Node.js + PostgreSQL on AWS. Their stack:
- 5×
m5.xlargeEC2 instances running the API - 2×
db.r5.2xlargeRDS instances (primary + replica) - 1× ElastiCache Redis (
cache.m5.large) - S3 for assets, CloudFront for delivery
- NAT Gateway, Application Load Balancer, Route 53, CloudWatch logs
Nothing exotic. The problem wasn't the architecture — it was that nothing had been re-evaluated since the original provisioning during a 2022 traffic spike that never repeated.
Lever 1: Right-sizing EC2 (saved ~$2,800/mo)
The first thing we did was pull two weeks of CloudWatch metrics. The story was clear: peak CPU across all five EC2 instances rarely exceeded 22%. They were running 4× the compute they needed.
The fix: dropped to 3× m6i.large instances (newer generation, smaller, cheaper per hour). Performance was actually slightly better — newer Intel chips, faster network — and the monthly EC2 line dropped from $3,400 to about $600.
Lever 2: RDS right-sizing + reserved instances (saved ~$2,400/mo)
RDS was the single biggest line item. The db.r5.2xlarge primary was running at 8% average CPU. The replica was running at 3%.
We dropped the primary to db.r6g.large (Graviton — 30% cheaper per core for the same workload) and the replica to db.r6g.large as well. Then we committed to 1-year reserved instances for both — another 35% off the on-demand rate.
The catch: you must be sure you'll keep the instances running for the term. RIs are not refundable. We only commit to RIs after eight weeks of stable post-optimisation metrics.
Lever 3: S3 lifecycle policies (saved ~$900/mo)
The client had three years of accumulated customer uploads sitting in S3 Standard. Most of it hadn't been accessed in over six months. We set up a lifecycle policy:
- After 30 days → S3 Standard-IA
- After 90 days → S3 Glacier Instant Retrieval
- After 365 days → S3 Glacier Deep Archive
Total S3 storage cost dropped by about 70%. The customer-facing impact was zero — recent uploads stayed on Standard, and the older files still came back in milliseconds when occasionally needed.
Lever 4: NAT Gateway → NAT Instance (saved ~$700/mo)
This one is controversial. NAT Gateway is AWS's managed service — easy, reliable, and surprisingly expensive at $0.045/hour plus data processing fees. The client was paying about $750/month just for NAT.
We replaced it with a single t4g.nano NAT instance running fck-nat. Cost: about $4/month. Caveat: we set up a clear runbook for failover, and the client accepted the slightly higher operational responsibility. Not the right call for every team, but the right call here.
Lever 5: CloudWatch logs retention (saved ~$600/mo)
CloudWatch was quietly accumulating logs with infinite retention. Three years of debug logs from every Node.js process. We:
- Set log group retention to 30 days for app logs, 90 days for audit logs
- Deleted accumulated logs older than 6 months
- Moved long-term audit retention to S3 Glacier (cheaper, still compliant)
Result: CloudWatch ingest and storage charges dropped from $720 to under $100 a month.
The smaller wins that added up
- Switched ElastiCache to a smaller node ($120/mo saved)
- Deleted three unused EBS volumes from a deprecated service ($45/mo)
- Moved CloudFront to the new pricing tier ($90/mo)
- Killed an unused Elastic IP ($4/mo)
- Right-sized the ALB targets ($60/mo)
Individually small. Together they trimmed another $300/month.
The biggest lesson: nothing here was novel. Every win was a config that hadn't been re-evaluated in 12+ months. AWS bills don't grow because of architecture — they grow because nobody is looking.
How to start on your own bill
Before you call us (or any consultant), here's the 90-minute audit you can do this afternoon:
- Open AWS Cost Explorer. Sort by service. Find your top 3 line items.
- For each top line item, pull two weeks of CloudWatch metrics. Look for peak utilisation.
- If peak is under 40%, you're probably over-provisioned.
- Check S3 lifecycle policies. If they don't exist, set them up.
- Check CloudWatch log retention. If it's "Never expire", it's costing you.
That alone will usually find 20–30% of savings. The remaining 30% comes from RIs, Savings Plans, and the deeper architectural work — which is where having someone who does this every week actually helps.
If you'd like us to take a look at your AWS bill, we offer a one-time fixed-fee cloud audit. You get a written report of every line item, every recommendation, and the expected savings — yours to act on with us, with someone else, or on your own.