Six months ago, my AWS bill was a manageable 200 dollars per month. By last month, it had ballooned to 847 dollars — and I had no idea why. My app had not grown significantly, my traffic was roughly the same, and I had not launched any new services. Something was wrong, and I needed to figure out what was eating my budget before it got worse.
The Investigation: Where Was the Money Going?
I started by opening AWS Cost Explorer and breaking down my spending by service. The results were eye-opening. EC2 instances accounted for 340 dollars — I had forgotten to terminate three test instances I created months ago. RDS was costing 180 dollars — my database was running on a db.r5.large instance that was massively oversized for my actual usage. S3 was 120 dollars — I had old backups and log files accumulating for months without any lifecycle policy. Data transfer was 95 dollars — my app was transferring data between regions unnecessarily. The remaining 112 dollars was spread across various services I barely used.
Fix 1: Terminate Zombie Instances (Saved 180 dollars)
The easiest win was terminating the three forgotten EC2 instances. They were t3.medium instances running 24/7 doing absolutely nothing. I also found two unused Elastic IP addresses that were costing 3.60 dollars each per month. Lesson learned: always tag your resources with a purpose and set up billing alerts for unexpected charges.
Fix 2: Right-Size My Database (Saved 120 dollars)
My RDS instance was a db.r5.large with 16GB of RAM, but my database was only using 2GB. I took a snapshot, created a new db.t3.medium instance from the snapshot, and pointed my app to the new instance. The migration took 15 minutes of downtime and saved me 120 dollars per month. I also enabled auto-scaling for storage so I would not overpay for unused disk space.
Fix 3: S3 Lifecycle Policies (Saved 80 dollars)
I created lifecycle policies to move old objects to S3 Glacier after 30 days and delete them after 90 days. I also deleted 500GB of old log files that I would never need again. The immediate deletion saved about 12 dollars, and the lifecycle policies will prevent the problem from recurring.
Fix 4: Reserved Instances (Saved 100 dollars)
For my production EC2 instance that runs 24/7, I purchased a 1-year reserved instance. This gave me a 40% discount compared to on-demand pricing. The upfront cost was higher, but the monthly savings more than compensated. I only did this for instances I was certain I would need for at least a year.
Fix 5: CloudFront for Static Assets (Saved 50 dollars)
My app was serving static files directly from EC2, which meant every image and CSS file was going through my server and incurring data transfer charges. I moved all static assets to CloudFront, which reduced my data transfer costs significantly and also improved page load times for users far from my server region.
The Result
After implementing all five fixes, my monthly bill dropped from 847 dollars to 320 dollars — a 62% reduction. The entire optimization process took one weekend. The most important lesson I learned is that AWS costs creep up silently if you are not actively monitoring them. I now have weekly billing alerts set up and review my Cost Explorer dashboard every Monday morning. Prevention is much easier than cure when it comes to cloud costs.
