A client came to us with an AWS bill that had grown from roughly ₹4 lakh to ₹19 lakh a month over two years, while traffic had roughly doubled. They assumed they needed to renegotiate with AWS. They needed to look at what they were running.
Week one: find out where the money goes
You cannot optimise an invoice you cannot read. The first job was tagging — every resource labelled with team, environment and service. That alone took four days and immediately surfaced 62 untagged EC2 instances that no one could account for.
Once Cost Explorer could group by tag, the picture was blunt:
| Category | Share of bill | Notes |
|---|---|---|
| EC2 (non-production) | 31% | Running 24×7 for an 8-hour workday |
| RDS | 22% | Two instances sized for a load test from 2023 |
| EBS & snapshots | 14% | Nearly half unattached or orphaned |
| NAT Gateway data | 11% | S3 traffic routed through NAT, not a VPC endpoint |
| Production compute | 18% | The only line genuinely earning its cost |
| Everything else | 4% |
The quick wins — first two weeks, no code changes
Schedule non-production environments
Development and staging ran continuously for a team working roughly 50 hours a week. A Lambda-driven start/stop schedule cut that spend by about 68% with a manual override for anyone working late.
Delete orphaned storage
1.4 TB of unattached EBS volumes and 900 snapshots older than eighteen months, most from instances long since terminated. We archived what had any plausible value to Glacier and deleted the rest.
Add a VPC endpoint for S3
All S3 traffic was leaving through a NAT Gateway at ₹3.7 per GB. A gateway endpoint costs nothing and removed that line almost entirely. This is the single most common avoidable cost we find.
Rightsize the obvious
Two RDS instances were provisioned for a load test that ended in 2023 and never resized. CloudWatch showed peak CPU at 11%. Two steps down, with a rollback plan, changed nothing operationally.
Result after two weeks: 28% reduction. No application changes, no downtime.
The slower work — one quarter
Commitment-based pricing
With usage stabilised, we could finally commit safely. A three-year Compute Savings Plan covering the baseline load, leaving burst capacity on demand, delivered a further 9%. The sequence matters: buying commitments before rightsizing locks in your waste.
Storage lifecycle policies
Document storage had no lifecycle rules at all. Objects untouched for 90 days moved to Infrequent Access, and to Glacier Instant Retrieval after a year. Retrieval patterns confirmed under 2% of objects older than 90 days were ever read.
The one architectural change
A nightly report job spun up a large instance for four hours to process a queue that averaged twenty minutes of real work. We moved it to a container task triggered by queue depth. That workload's cost fell by roughly 85%, and reports arrived earlier.
Where we landed
The monthly bill settled at about ₹10.4 lakh — a 45% reduction — while serving 30% more traffic than when we started. Cost per transaction fell by roughly 58%.
Keeping it there
Savings decay without governance. What we left behind:
- A mandatory tagging policy enforced by an AWS Config rule — untagged resources are flagged daily.
- Per-team cost dashboards with a monthly showback, so engineering sees the effect of its decisions.
- Budget alerts at 80% and 100% of the forecast, routed to the team that owns the spend.
- A quarterly rightsizing review as a standing calendar item, not a project.
Cloud cost is an engineering metric, not a finance one. It moves when the people making architectural decisions can see the number their decisions produce.