Cloud bills grow quietly — a forgotten test instance, an over-provisioned database, storage that was never moved to a cheaper tier. None of it looks dramatic individually, and all of it compounds. Here's where the real leverage is.
Right-sizing: the single biggest lever
Most workloads are provisioned generously "to be safe" and never revisited once running. Cloud providers' own cost tools (AWS Cost Explorer, Azure Advisor, GCP Recommender) surface instances running consistently under 20-30% CPU/memory utilization — these are near-guaranteed candidates for a smaller instance size at meaningfully lower cost with no performance impact.
Before: m5.2xlarge running at 15% average CPU utilization
After: m5.large — same workload, quarter of the cost
This alone is usually the highest-leverage change available, and it requires no architectural work — just resizing based on data you likely already have.
Reserved / committed-use pricing for predictable workloads
On-demand pricing carries a real premium for flexibility you may not need. For workloads you know will run continuously for a year or more (a production database, a baseline of always-on application servers), committing to reserved instances (AWS), reserved VM instances (Azure), or committed-use discounts (GCP) typically cuts 30-60% off the on-demand rate for that exact same resource — you're just pre-paying for capacity you were going to use anyway.
The key qualifier: only commit for genuinely predictable, steady-state workloads. Committing on capacity you might scale down or migrate away from locks in cost without the corresponding flexibility.
Storage tiers — the "set and forget" waste
Object storage (S3, Azure Blob, GCS) defaults to its most expensive, most-available tier. Data that's rarely accessed after creation — logs older than 90 days, backups, archived reports — belongs in a cheaper tier (S3 Glacier, Azure Archive, GCS Coldline), often at a fraction of standard storage cost.
Lifecycle rule: after 30 days → move to Infrequent Access tier
after 90 days → move to Archive tier
after 365 days → delete
Setting this up once as a lifecycle policy means it happens automatically going forward — no one has to remember to do it manually, which is exactly why it's so commonly left undone without automation.
Autoscaling instead of static over-provisioning
Provisioning for peak load 24/7, when peak only happens for a few hours a day, means paying peak-capacity prices around the clock. Autoscaling (scaling compute up during high demand, down during low demand) matches spend to actual usage instead of worst-case usage — genuinely useful for workloads with real daily/weekly traffic patterns, less useful for workloads that are already flat and constant.
The habit that actually prevents waste: tagging and attribution
Cost optimization efforts stall when nobody can tell which team or project a given cost belongs to — a large, unattributed bill is hard to act on. Consistently tagging resources (by team, environment, project) turns a single opaque number into a breakdown you can actually investigate and assign ownership to.
Tag: team=payments, environment=production, project=checkout-service
The practical order of operations
- Turn on cost tagging/attribution first — without it, you're optimizing blind.
- Right-size based on actual utilization data — the highest-leverage, lowest-effort change.
- Move eligible storage to cheaper tiers via lifecycle policies.
- Commit to reserved capacity only for workloads you're confident are staying stable.
- Revisit regularly — cost optimization isn't a one-time project, since new waste accumulates the same quiet way the original waste did.