Cloud cost optimization

AWS cost optimization without breaking production

AWS cost optimization works best when the person cutting the bill also understands the application. Dashboards can tell you an instance is underused; they can’t tell you it’s the one that absorbs the month-end batch job. I find the spend that isn’t buying you anything, remove it safely, and change the architecture where that’s where the money really goes.

I’ve designed and run production systems on AWS and Google Cloud for years – at WixelHQ, the studio I co-founded, and on platforms like Indiemaker. The same principles apply to Google Cloud and Azure; the service names change.

Start with where the money goes

Before changing anything I want the bill broken down by service, account, environment and team. That means:

  • Cost Explorer grouped by service and usage type – the usage type column is where surprises hide, like NAT Gateway bytes or CloudWatch log ingestion.
  • Cost and Usage Reports exported to S3 and queried with Athena, for line-item detail per resource.
  • Cost allocation tags enforced on new resources (environment, service, owner). Untagged spend is unowned spend.
  • Budgets and anomaly detection so the next spike is an alert on day one, not a surprise on the invoice.

The fixes that usually pay off first

  1. Delete what nobody uses. Unattached EBS volumes, old snapshots and AMIs, idle load balancers, forgotten dev environments, Elastic IPs not attached to anything.
  2. Rightsize compute. Compute Optimizer and CloudWatch metrics show instances running at single-digit CPU. Resize in steps and watch p95 latency, not just averages. Move to Graviton instance types where your runtime and dependencies support ARM.
  3. Fix data transfer. NAT Gateway processing charges add up fast. VPC gateway endpoints for S3 and DynamoDB route that traffic privately and remove the NAT processing cost. Cross-AZ chatter between services and a database in another AZ is another common leak.
  4. Right-tier storage. gp2 volumes migrated to gp3, S3 lifecycle rules moving old objects to cheaper classes, Intelligent-Tiering for unpredictable access patterns, and log retention set to something other than “forever”.
  5. Commit only after rightsizing. Compute Savings Plans or Reserved Instances on the stable baseline once it’s the right size – committing first locks in waste for one to three years.
  6. Use Spot where interruption is fine: CI runners, batch jobs, stateless workers behind a queue.

The database is often the biggest line

Managed databases are frequently the largest single item, and they’re oversized because nobody wants to be the person who shrank the database before an outage. The safer route is to make the workload cheaper first:

  • Find the expensive queries with pg_stat_statements or CloudWatch Database Insights (the successor to Performance Insights) and fix them. A missing index can be the difference between a large instance and a small one. See PostgreSQL performance tuning.
  • Move read-heavy reporting to a read replica, or out of the primary entirely.
  • Check whether provisioned IOPS are actually used, and review whether Aurora’s I/O-Optimized or standard configuration fits your I/O pattern.
  • Turn non-production databases off outside working hours.

Architecture-level savings

Past the quick wins, real savings come from design changes: caching hot reads instead of scaling the database (caching strategy), serving static assets and media through a CDN, replacing always-on workers with queue-driven autoscaling, batching chatty service-to-service calls, and consolidating a sprawl of tiny microservices that each carry a fixed overhead.

These take longer, so I only recommend them when the numbers justify the engineering time.

When to do this yourself

If your bill is small relative to revenue, the quick wins above are a good afternoon for any engineer and you don’t need outside help. Bring someone in when the bill is large, growing faster than usage, or the obvious fixes are done and the remaining spend is tangled up in the architecture. If you’re mid-move between platforms, sort out the migration first and optimize on the destination.

Questions

How can I reduce my AWS bill quickly?

Delete unused resources, rightsize oversized instances and databases, migrate gp2 volumes to gp3, add S3 gateway endpoints to cut NAT Gateway charges, and set log retention. Then buy Savings Plans for the stable baseline. Do them in that order so you don’t commit to waste.

Are Savings Plans or Reserved Instances better?

Compute Savings Plans are more flexible – they apply across instance families, regions and Fargate or Lambda. For databases such as RDS, compare Reserved Instances with the newer Database Savings Plans – RIs usually discount a steady instance more, the Savings Plan is more flexible. Either way, only commit after rightsizing, and cover the steady baseline rather than peak.

What is cloud cost optimization?

Cloud cost optimization is the ongoing work of matching what you pay for to what you actually use: removing idle resources, rightsizing, choosing the right pricing models and storage tiers, and changing architecture where it drives cost. It works best when engineers own their spend.

Will cutting costs hurt performance or reliability?

It shouldn’t if it’s done carefully. Rightsize in steps, watch latency percentiles and error rates after each change, and never remove redundancy like multi-AZ databases just to save money. Most savings come from waste, not from running closer to the edge.

AWS bill growing faster than your customers?

Share a cost breakdown by service. In a two-week sprint I’ll find the biggest waste, ship the safe fixes and size up the architectural ones.

GMT+2 · Full EU overlap · US East mornings

Related