← All posts

How to Reduce AWS Costs Without Slowing Your Team Down

Back when I was CTO at Skuola.net, tightening up infrastructure spend cut around 30% off the initial IT budget, without touching a single feature. Nobody made one big reckless decision to get there in the first place, and nobody made one big smart decision to fix it either. It was a lot of small, reasonable choices, a larger instance to unblock a launch, an environment nobody turned off, a storage tier nobody revisited, quietly compounding into a number finance couldn’t explain.

If your AWS bill keeps climbing while headcount and traffic stay roughly flat, the problem usually isn’t that you’re using too much cloud. It’s that spend has drifted away from value and nobody owns the gap.

Measure before you touch anything.

The instinct when a bill grows is to start cutting, but cutting before you can see is how you break production on a Friday and quietly turn the savings back on a month later. Cost allocation tags, Cost Explorer and the Cost and Usage Report someone actually reads, and a dashboard that maps spend to teams turn a scary aggregate number into a set of specific line items. If you’re on Kubernetes, OpenCost does the same job for per-namespace and per-workload spend, which AWS’s own tools don’t split out on their own. That shift, from “the bill is too high” to “these six things are the bill,” is where the real savings start. Ask which services and teams actually drive the spend, what’s running right now that nobody’s using, where cross-AZ and cross-region traffic hides, and how much you’re paying on-demand for load that’s entirely predictable.

Once you can see it, a handful of categories tend to account for most of the recoverable spend. Over-provisioned compute, sized for a peak that arrives twice a year and never revisited since. Idle and zombie resources: non-production running 24/7 for something used 40 hours a week, load balancers pointing at nothing, an Elastic IP billed precisely because it’s not attached. I ran into a smaller version of this on my own home server rack, of all places, same instinct, much smaller scale. Storage that never gets curated, logs and backups sitting on the expensive tier because nobody set a lifecycle policy. And on-demand pricing for load you could forecast a year out, which is exactly what Savings Plans and Reserved Instances are for, once you’ve right-sized and know what baseline you’re actually committing to.

Three of those categories are quick enough to check right now, before any dashboard is even set up:

# Unattached EBS volumes — billed whether or not anything uses them
aws ec2 describe-volumes --filters Name=status,Values=available \
  --query 'Volumes[].[VolumeId,Size,CreateTime]' --output table

# Elastic IPs not attached to anything — billed precisely because they're idle
aws ec2 describe-addresses \
  --query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' --output table

# Load balancers with zero healthy targets — paying for a router to nowhere
aws elbv2 describe-target-health --target-group-arn <arn> \
  --query 'TargetHealthDescriptions[?TargetHealth.State!=`healthy`]'

Run the first two against every region you actually use, not just the default one, that’s where these tend to hide. Right-sizing has a bad reputation because it’s usually done blind, someone drops instance sizes on a Friday and spends Monday firefighting. Done properly it’s boring, in the best way: get real utilisation numbers first (AWS’s own Compute Optimizer will tell you exactly which instances are oversized, for free), change one class of thing at a time so you can tell what broke if something does, and start with non-production to build confidence before touching anything customer‑facing. Graviton instances are worth testing early too, often comparable performance for less money. Infracost is worth wiring into the pull request itself if you manage infrastructure with Terraform, so the cost of a change shows up before it merges instead of on next month’s bill.

None of this holds if it’s a one‑off. What tends to actually stick is a handful of habits: spend tagged and owned by the team that can see it, an alert when something breaks its expected envelope instead of a quarterly surprise, and cost showing up as a real input at architecture review time instead of an afterthought. It’s also where GreenOps and FinOps overlap more than people expect, idle compute doesn’t just cost money, it burns energy for nothing, so right‑sizing tends to cut cost and carbon at the same time.

A climbing AWS bill is a visibility problem before it’s a spending problem. Measure it honestly, fix the safe wins first, and put just enough governance in place that the savings don’t quietly erode the moment nobody’s watching.