Find out where the money actually goes
Every cost engagement starts the same way: a tagging audit. If resources are not tagged by service, environment and owner, the bill is one undifferentiated number and every conversation about it is speculation. Enforcing tags — and blocking untagged resource creation — is unglamorous and it is the prerequisite for everything else.
Once tagged, the breakdown is usually surprising. On this platform, non-production environments accounted for roughly a third of compute spend, largely because staging and development ran the same instance sizes as production, around the clock, for a team working eight hours a day in one time zone.
Stop paying for idle non-production
The single largest saving required no architectural insight at all: schedule non-production environments off outside working hours. Running development and staging 168 hours a week to serve roughly 50 hours of use is paying more than three times what you need. A scheduled scale-to-zero, with a self-service way for engineers to wake an environment, fixed it.
The objection is always that someone might need it at 10pm. In practice, a one-click wake taking two minutes covered that entirely. I mention this first because teams reach for sophisticated optimisations while the largest, simplest saving sits untouched in their non-production account.
Right-size on evidence, not on comfort
Instance sizes are usually chosen once, generously, and never revisited. Pulling actual utilisation showed a fleet running at low single-digit CPU with modest memory use, sized for a peak that had been estimated rather than measured. Right-sizing based on observed percentiles, with headroom for genuine peaks, cut the compute footprint significantly.
The discipline is to size for the 95th percentile plus headroom and let auto-scaling handle the rest, rather than sizing every instance for the annual worst case. That is what auto-scaling is for, and paying peak prices continuously to avoid configuring it is a common and expensive trade.
Storage lifecycle is free money
S3 buckets accumulate. Logs, backups, exports, temporary artefacts that were never temporary. Without lifecycle rules everything sits in standard storage forever at standard prices. Adding transition rules — infrequent access after a period, archival after longer, expiry for genuinely transient data — reduced storage cost substantially and took an afternoon.
Two related items are consistently missed: unattached EBS volumes left behind by terminated instances, and old snapshots retained by a backup policy with no expiry. Both are pure waste, and both are trivially found once tagging exists. Neither has any architectural consequence to clean up.
Asynchronous processing changes the cost curve
The platform did report generation and file processing synchronously inside web requests. That meant the web tier had to be sized for the heaviest operation any user might trigger, so every instance was large to accommodate work that happened occasionally.
Moving that work to a queue with separate workers let the web tier shrink to what it actually needs for request handling, while workers scale independently on queue depth and can be far more aggressive about scaling to zero. This was the one change with real architectural content, and it improved responsiveness at the same time as cost — the two goals were not in tension.
Commitments last, after the shape is stable
Reserved capacity and savings plans offer substantial discounts, and the mistake is buying them first. Committing to a footprint before right-sizing locks in the waste — you get a discount on resources you should not be running. Optimise the architecture, let it stabilise, then commit to the steady-state baseline.
I commit only to the reliable floor and leave the variable portion on demand. That preserves the flexibility to keep optimising without stranding a commitment, which is what happens to teams who buy three-year reservations and then discover they can halve their footprint.
Key takeaways
- Enforce tagging first — an untagged bill makes every cost conversation guesswork
- Schedule non-production environments off outside working hours; 168 hours of uptime for 50 hours of use is the biggest easy win
- Right-size on observed utilisation percentiles with headroom, and let auto-scaling cover peaks
- Configure S3 lifecycle rules and delete orphaned EBS volumes and expired snapshots — pure waste, no architectural risk
- Move heavy occasional work to queues and workers so the web tier is sized for requests, not for its worst operation
- Buy reserved capacity last, only against the stable baseline, or you lock in the waste you had not yet removed
Conclusion
Cloud cost work is rarely clever. It is tagging, scheduling, right-sizing, lifecycle rules, and moving heavy work off the request path — in that order, because each step changes the footprint the next one measures. Commit to reservations only once the shape has stopped moving.
Enjoyed this article?

Vivek Kumar Singh
Technical Expert · Full Stack Cloud Engineer · Tokyo, Japan