Autostat

Cloud cost optimisation: how to reduce your AWS bill and keep it down

Why a large AWS bill gets that way, fourteen ways to reduce AWS costs roughly in order of payoff, the same ideas on Azure and Google Cloud, the tools worth using, and the automation that stops the bill drifting back up.

Performance analytics graphs on a laptop screen
A cost dashboard only helps if somebody owns it. Photo: Luke Chesser, Unsplash.

Why is my AWS bill so high?

It's the question behind most of the cloud cost optimization work we do, usually followed by "how to reduce AWS bill without breaking anything", and the answer is nearly always the same handful of causes:

  • Resources outlive the project. Instances, databases, load balancers and volumes spun up for a feature, a test or a migration, still running long after the work shipped.
  • Non-production runs 24 hours a day. Dev, staging and QA sized like production and left on overnight and all weekend, serving nobody.
  • Capacity sized for a peak. Picked for a launch or a scary week, never resized when the week ended.
  • Storage never gets deleted. Snapshots, old log groups, S3 object versions, backups of backups. Deleting feels riskier than paying, so nobody deletes.
  • Data travels further than it needs to. Cross-AZ chatter, NAT gateways, internet egress. None of it shows on the architecture diagram.
  • No line item has an owner. Without tags and a sensible account structure, no team sees its own spend, so nobody acts.
  • Discounts never bought, or bought wrong. On-demand pricing on workloads that haven't changed in a year, or a three-year Reserved Instance on an instance size that was wrong to begin with.

None of these is dramatic. That's why they survive every budget review.

Diagram of where a large AWS bill typically hides: compute sized for a peak, non-production running all night, orphaned storage, logs kept forever, NAT and data transfer, on-demand pricing on steady workloads
Typical sources of waste on a large AWS account. Not to scale; your baseline tells you the real proportions.

Cloud cost optimisation strategies: three passes

Every cloud cost management approach that actually works boils down to the same loop. See the bill, cut the waste, automate the controls, then do it again next month with the same owner. Most teams do the first two once. The third is what keeps the bill down.

Diagram of the three passes of cloud cost optimisation: visibility, cut waste, automate, repeated monthly
It's a loop, not a project. The third pass is the one most teams skip.

Pass one: find where the money goes

Resist the urge to start deleting. Make the bill readable first.

  1. AWS Cost Explorer, grouped by service, then linked account, then tag. Find your top five services. On most accounts a handful dominate: EC2, RDS, S3, data transfer and EBS, with EKS, CloudWatch and NAT gateways not far behind.
  2. Turn on the AWS Cost and Usage Report (CUR, now part of Data Exports) into S3 and query it with Athena if the account is big. Cost Explorer is a summary; the CUR is the truth, down to individual resource IDs.
  3. Activate AWS cost allocation tags for owner, environment and product, and measure what's left unallocated. Untagged spend is unowned spend, and it goes first on the list.
  4. Write down a baseline. A full month by service and environment, with the usage behind it. Every change you make later is measured against this, so savings are evidence rather than vibes.
  5. Open AWS Cost Optimization Hub, Compute Optimizer and Trusted Advisor. They don't catch everything, but they're free and they hand you a starting list of idle resources, rightsizing candidates and commitment recommendations.

A query like this against the CUR is a decent first look at where unowned spend sits:

SELECT line_item_product_code,
       resource_tags_user_owner,
       SUM(line_item_unblended_cost) AS cost
FROM cur
WHERE year = '2026' AND month = '9'
GROUP BY 1, 2
ORDER BY cost DESC
LIMIT 50;

Pass two: 14 ways to reduce AWS costs

Roughly in order of payoff for effort on the accounts we see. Yours will differ; the baseline tells you where to start.

1. Delete what nobody is using

Unattached EBS volumes. Snapshots of volumes that no longer exist. Load balancers with no healthy targets. Public IPv4 addresses sitting idle (AWS charges for those now). Stopped instances still paying for their disks. Empty EKS clusters. OpenSearch domains nobody queries. This is the cheapest money you will ever save, and it needs three things: a list, an owner and a deletion date.

# Volumes attached to nothing, with size and age
aws ec2 describe-volumes --filters Name=status,Values=available \
  --query 'Volumes[].{id:VolumeId,gb:Size,created:CreateTime}' --output table

2. Rightsize EC2 before anything else

Put CloudWatch CPU, memory (you need the agent for memory) and network next to the instance size. Compute Optimizer does most of the maths. Do it before buying any commitment, or you'll lock in the oversized footprint for a year.

3. Switch non-production off when nobody's working

If dev and staging only run during working hours, you save most of their cost without touching production. Instance Scheduler on AWS, a Lambda on an EventBridge cron, or simply destroying whole environments defined in Terraform all work. Make "off" the default and "on" the exception.

# EventBridge schedules: stop the dev environment at 19:00, start at 07:30, Mon to Fri
StopDev:  cron(0 19 ? * MON-FRI *)
StartDev: cron(30 7 ? * MON-FRI *)

4. Move to current-generation and Graviton instances

Newer families give better price-performance, and Graviton (Arm) instances are cheaper for the same work wherever your software supports it, which is most Linux workloads, managed databases and container images these days. One change, paid back every month.

5. Tier S3 and fix EBS

S3 lifecycle rules to move objects to Infrequent Access or Glacier classes, expire old versions, and abort incomplete multipart uploads (which quietly cost money). Intelligent-Tiering where you honestly don't know the access pattern. Migrate EBS from gp2 to gp3: cheaper per gigabyte, and IOPS and throughput are set separately. Give snapshots and AMIs a retention policy.

{
  "Rules": [{
    "ID": "logs-tier-and-expire",
    "Filter": { "Prefix": "logs/" },
    "Status": "Enabled",
    "Transitions": [{ "Days": 30, "StorageClass": "STANDARD_IA" },
                    { "Days": 90, "StorageClass": "GLACIER_IR" }],
    "Expiration": { "Days": 400 },
    "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 7 }
  }]
}

6. Reduce RDS costs

Idle or oversized instances, provisioned IOPS nobody needed, Multi-AZ on databases that aren't production, read replicas created during an incident and never removed, and backups retained far beyond the recovery point anyone actually requires. Graviton instance classes and gp3 storage apply here too. For spiky workloads, Aurora Serverless can replace an always-on instance sized for the busiest hour of the year.

7. Reduce data transfer costs

Cross-AZ traffic is billed in both directions, so chatty services spread across zones add up. Keep them together where resilience allows, put CloudFront in front of anything served to the internet repeatedly (transfer from CloudFront is cheaper than straight from EC2 or S3), and compress what you send.

8. Reduce NAT gateway costs

NAT gateways bill per hour and per gigabyte processed, and a surprising amount of that traffic is your own services talking to S3, DynamoDB or ECR. Gateway VPC endpoints for S3 and DynamoDB carry no data processing charge; add interface endpoints for other AWS services you hit hard. The VPC Flow Logs for the NAT's network interface will tell you who the big talkers are.

9. Reduce CloudWatch costs

Logs ingestion and storage, custom metrics and high-resolution alarms all scale with volume, not value. Set a retention period on every log group (the default is "never expire"), filter debug noise before it's ingested, use the Infrequent Access log class for logs you keep for audit rather than debugging, and ask who actually looks at each dashboard.

# Log groups with no retention set, i.e. kept forever
aws logs describe-log-groups --query 'logGroups[?!retentionInDays].logGroupName'

10. Reduce AWS Config costs

AWS Config charges per configuration item recorded, so busy accounts with continuous recording of every resource type can run up a real bill, especially with Kubernetes or autoscaling churn. Record only the resource types your rules and audits need, and switch non-critical types to daily (periodic) recording.

11. Kubernetes cost optimization on EKS

On EKS you pay for node hours, not pod usage. Compare container requests with real usage, set requests honestly, let Karpenter or the cluster autoscaler size nodes to demand, and put tolerant workloads on Spot. Something that maps spend to namespaces (OpenCost is free) makes it visible to the teams who own the workloads, which is when it starts to improve.

12. AWS Savings Plans vs Reserved Instances

Both discount steady usage in exchange for a one- or three-year commitment. How do AWS Savings Plans work? You commit to a fixed amount of compute spend per hour, and anything up to that amount is billed at the discounted rate. Compute Savings Plans apply across EC2 families, regions, Fargate and Lambda; EC2 Instance Savings Plans and Reserved Instances discount a bit more but tie you to a family or region. Reserved Instances are still the only commitment option for RDS, ElastiCache, OpenSearch and Redshift. Buy after rightsizing and scheduling, cover a conservative share of the baseline, and check coverage and utilisation monthly. Over-committing is a very expensive way to feel organised.

13. Use Spot for anything that can be interrupted

Batch jobs, CI runners, data processing, rendering, stateless workers. All fine on Spot at a large discount from on-demand, as long as you design for interruption: checkpoints, several instance types, and no stateful or latency-sensitive services.

14. Change the architecture when the bill tells you to

Some costs are structural. A service that polls instead of listening to events. A cache that never got added. A job running hourly when daily would do. A monolith sized for its busiest endpoint. These take longer and belong on the roadmap, but they're what keeps a bill flat while usage grows.

The same approach on Azure and Google Cloud

The mechanics transfer almost one to one. On Azure, Cost Management and Advisor stand in for Cost Explorer and Compute Optimizer, Reservations and Azure savings plans for Savings Plans, and blob lifecycle management for S3 lifecycle rules. On Google Cloud it's Billing reports and Recommender for finding idle and oversized resources, committed use discounts for steady workloads, and Autoclass or lifecycle rules on Cloud Storage. The order of work is identical: visibility, waste, rightsizing, scheduling, commitments, architecture.

Cloud cost optimisation tools worth using

You don't need to buy anything to start. A sensible toolbox, most of it free:

ToolWhat it's forCost
AWS Cost ExplorerSpend by service, account and tagFree in the console
Cost and Usage Report + AthenaLine-item truth, per resourceS3 and Athena query costs
AWS Cost Optimization HubIdle resources, rightsizing and commitment ideas in one listFree
AWS Budgets and Cost Anomaly DetectionAlerts on thresholds and unexpected jumpsFree tier, then small
Compute OptimizerRightsizing for EC2, EBS, Lambda, RDSFree basic tier
OpenCostKubernetes cost by namespace and workloadOpen source
InfracostCost estimate on every Terraform pull requestOpen source CLI
Cloud CustodianPolicies that find and clean up waste on a scheduleOpen source

Commercial FinOps platforms earn their keep once you have many accounts, several clouds or showback to lots of teams. Buy a tool to support a practice, not instead of one.

Cloud cost optimisation best practices: prioritise by value, effort and risk

Not every finding deserves action. For each one, estimate the monthly saving, the effort to do it and the operational risk, then sort.

  • Quick wins: idle resources, retention policies, scheduling, gp3, log retention. Low effort, low risk, start this week.
  • Planned changes: rightsizing production, Graviton, NAT and endpoint changes, Kubernetes requests. These need a test window and a named owner.
  • Commitments: once the first two groups have settled the baseline, so you commit to the right footprint.
  • Architecture: on the roadmap, justified by the line item it removes.

Measure every change against the baseline and watch latency, error rates and headroom while you do it. A saving that degrades the service isn't a saving, it's a cost you've moved somewhere less visible.

Pass three: automate it so the bill doesn't creep back

Most teams can cut a bill once. Keeping it down is the hard part, because every habit that created the waste is still there. This is the pass people skip, and it's why the same account gets "optimised" again eighteen months later.

Enforce tagging

Pick a small set of required tags (owner, environment, product, cost centre), enforce them with Organizations tag policies and the required-tags AWS Config rule, and fail the Terraform plan when they're missing.

variable "tags" {
  type = map(string)
  validation {
    condition     = alltrue([for k in ["owner", "env", "product"] : contains(keys(var.tags), k)])
    error_message = "owner, env and product tags are required."
  }
}

Budgets and AWS cost anomaly detection

AWS Budgets per account, team or service, with alerts at thresholds that mean something, plus Cost Anomaly Detection for the sudden jumps budgets miss. Send the alert to the channel of the team that owns the spend. A shared finance inbox is where cost alerts go to die.

Make cleanup a scheduled job

Lifecycle rules for S3 and snapshots. Scheduled stop and start for non-production. A job (Cloud Custodian or a small Lambda) that deletes anything whose expires tag has passed. A weekly report of unattached volumes and idle load balancers. If a human has to remember it, it will be forgotten by March.

Put cost in the pull request

Estimate the cost of infrastructure changes at review time with Infracost, enforce instance family and size policies as code, and require a one-line justification for anything above a threshold. Review cost the way you review security: before merge, not after the invoice.

Keep rightsizing and commitments on a calendar

Recommendations refresh continuously; somebody has to read them. A monthly slot for rightsizing candidates, Savings Plan coverage and utilisation, and anything about to expire. Half an hour, same owner, every month.

Give every line item an owner

Show each team its own spend, dashboards or a monthly report, and make the trend part of their regular reviews. That's the core of FinOps: engineering, finance and product sharing responsibility for cloud spend. It matters more than any tool you could buy.

When to bring in cloud cost optimisation services

If the account is large, the team is flat out and nobody has owned cost before, an outside review is usually faster than finding the time internally. Decent cloud cost optimisation services do four things: analyse billing and usage data against the actual resources, produce a prioritised list with estimated savings, effort and trade-offs, implement what you approve, and measure the result against an agreed baseline while watching performance. They should also leave you with the budgets, alerts and ownership described above, so the bill stays down after they've gone.

That's how our AWS cost optimization service works, and you can pay for it two ways: a fixed fee where you keep every dollar saved, or nothing up front and a share of the verified saving for a limited period. For Azure and Google Cloud, see FinOps and cloud cost optimisation. Teams that want the operations side looked after too usually pair it with managed DevOps, or take the Secure SaaS Growth Bundle, which includes both. If you're still deciding whether an outside team makes sense at all, this guide to DevOps managed services covers that question.

Frequently asked questions

How much can cloud cost optimisation save?

It depends on how the account has been looked after so far. Accounts that have never been reviewed tend to carry more idle resources, oversized capacity and unbought commitments than ones with an existing FinOps habit. The honest answer comes from your billing data, which is why we quote actions with estimated savings rather than promising a percentage up front.

How do I reduce my AWS bill quickly?

Start with what carries no risk: delete unattached volumes, old snapshots, idle load balancers and unused IP addresses, set retention on CloudWatch log groups, move EBS to gp3, and schedule non-production environments to stop outside working hours. Rightsizing and commitments come next, once you have a baseline to measure against.

Will cutting cloud costs hurt performance or reliability?

Not if you do it in the right order and measure as you go. Deleting idle resources carries no performance risk. Rightsizing and scheduling need a test window and an eye on latency, errors and headroom. Commitments only change the price. Architecture changes are the ones to plan properly. A good review puts the trade-off next to every saving.

Should we buy Savings Plans or Reserved Instances first?

Neither, until you've rightsized and scheduled, otherwise you lock in a discount on capacity you didn't need. After that, Compute Savings Plans are the flexible default for EC2, Fargate and Lambda, and Reserved Instances cover RDS, ElastiCache, OpenSearch and Redshift. Cover a conservative share of steady usage and review utilisation monthly.

What is FinOps?

FinOps is the practice of making engineering, finance and product teams jointly responsible for cloud spend: everyone can see what they spend, decisions weigh cost against speed and reliability, and the work repeats on a regular cycle. In practice it means tagging, showback, budgets, anomaly alerts and a monthly review with named owners.

How often should we review cloud costs?

Alerts run all the time. A short monthly review of top services, anomalies, rightsizing recommendations and commitment coverage keeps things in line, and a deeper look once or twice a year catches structural drift. The cadence matters less than having a named owner for it.

Do we need a paid tool for AWS cost optimization?

Not to start. Cost Explorer, the Cost and Usage Report, Cost Optimization Hub, Budgets, Cost Anomaly Detection and Compute Optimizer cover most of what a single account needs, and OpenCost, Infracost and Cloud Custodian fill the gaps for free. Paid platforms make sense with many accounts, several clouds or showback to many teams.

What access does a cloud cost optimisation review need?

Read access to billing and usage data (Cost Explorer or the CUR) and read-only access to the accounts in scope, so recommendations are based on real resources and metrics rather than the bill alone. Nothing gets changed without approval, and any implementation work runs on separately authorised access.

Want this done on your account?

Tell us which clouds you run and roughly what you spend a month. We'll go through the account, rank the savings by value, effort and risk, and can implement what you approve and measure it against a baseline.