Reduce Your AWS Bill: 12 Cloud Cost Optimization Tactics (2026)

Khimananda Oli 9 min read Database
Reduce Your AWS Bill: 12 Cloud Cost Optimization Tactics (2026)

By Khimananda Oli | Last reviewed: August 2026

Most AWS bills are not big because the workload is big — they are big because nobody turned anything off. An over-provisioned instance, a forgotten load balancer, a terabyte of logs kept forever: each one is small, and together they can double what you pay. These 12 cloud cost optimization tactics to reduce your AWS bill are ordered from fastest win to deepest structural change, so you can start cutting spend this afternoon. If you would rather have someone run the audit for you, our DevOps and cloud services do exactly this.

Where the AWS bill leaksComputeover-provisionedEC2 / RDSon-demand onlyStorageS3 Standard foreverold snapshotsgp2 volumesData transferNAT Gatewaycross-AZ trafficegress to internetIdleunattached EBSunused EIPsstale load balancersMeasure first with Cost Explorer + Budgets, then attack the biggest leakyou cannot cut what you have not tagged and measured
The four places an AWS bill leaks — compute, storage, data transfer, and idle resources — and why measurement comes before any cost optimization.

How do you find out where your AWS bill is going?

You cannot reduce a bill you cannot see. Every real cost optimization program starts with visibility, so the first two tactics are about measurement, not cutting.

1. Turn on Cost Explorer and read it monthly

AWS Cost Explorer is free to enable and shows spend broken down by service, region, account, and — if you tag resources — by team or project. Open it, group by service, and sort descending. The top three lines are almost always EC2, RDS, and data transfer; that is where your effort pays off. Enable the hourly and resource-level granularity so Cost Explorer can drive right-sizing recommendations later.

2. Set AWS Budgets with alerts before you optimize

A budget is your safety net. Create at least one monthly cost budget and one that alerts on forecasted overspend, wired to email or SNS:

aws budgets create-budget \
  --account-id 111122223333 \
  --budget '{
    "BudgetName": "monthly-all-in",
    "BudgetLimit": {"Amount": "500", "Unit": "USD"},
    "TimeUnit": "MONTHLY",
    "BudgetType": "COST"
  }' \
  --notifications-with-subscribers '[{
    "Notification": {"NotificationType": "FORECASTED",
      "ComparisonOperator": "GREATER_THAN", "Threshold": 90},
    "Subscribers": [{"SubscriptionType": "EMAIL",
      "Address": "[email protected]"}]
  }]'

Now a runaway instance or a mis-scoped data pipeline pings you on day 4, not on the invoice.

Which idle and unused AWS resources should you delete first?

Deleting waste is the only tactic with zero downside — no performance trade-off, no commitment. Do it before anything clever.

3. Delete unattached EBS volumes and unused Elastic IPs

Every EBS volume bills whether or not it is attached to a running instance, and an Elastic IP that is allocated but not associated with a running instance is billed hourly. Find both quickly:

# Unattached EBS volumes
aws ec2 describe-volumes \
  --filters Name=status,Values=available \
  --query 'Volumes[].{ID:VolumeId,GiB:Size,AZ:AvailabilityZone}' \
  --output table

# Allocated Elastic IPs not associated with an instance
aws ec2 describe-addresses \
  --query 'Addresses[?AssociationId==`null`].PublicIp' \
  --output table

Snapshot anything you are unsure about, then delete. Old EBS snapshots pile up too — a lifecycle policy via Amazon Data Lifecycle Manager ages them out automatically.

4. Remove stale load balancers, NAT Gateways, and idle RDS

An Application or Network Load Balancer with no healthy targets still costs roughly $16+ a month plus capacity units. A NAT Gateway you spun up for a one-off migration keeps billing hourly and per-GB. Idle non-production RDS instances left running overnight are pure waste — schedule them to stop, or delete and restore from snapshot when needed.

How do you right-size AWS instances that are too big?

Over-provisioning is the single largest source of avoidable spend. Teams pick an instance size "to be safe" and never revisit it.

5. Right-size EC2 and RDS from real utilization

Use AWS Compute Optimizer (free) and Cost Explorer's right-sizing recommendations, both of which read CloudWatch metrics. The rule of thumb: if an instance sits below ~40% CPU and memory at peak for two weeks, drop it one size. Halving an m6i.2xlarge to an m6i.xlarge halves that line item. Right-size before you buy any commitment, so you commit to the smaller footprint — never the bloated one.

6. Modernize storage: gp3 over gp2, and clean CloudWatch logs

Migrating an EBS volume from gp2 to gp3 is a live modify with no downtime and is roughly 20% cheaper per GiB, with baseline throughput included. Separately, CloudWatch Logs with the default Never Expire retention quietly become one of your top bills. Set retention explicitly:

# gp2 -> gp3 in place, no downtime
aws ec2 modify-volume --volume-id vol-0abc123 --volume-type gp3

# Cap CloudWatch log retention at 30 days
aws logs put-retention-policy \
  --log-group-name /aws/lambda/my-fn \
  --retention-in-days 30
Right-size, then commit, then SpotEvery workloadstart here: right-sizeIs the load steady 24/7?Steady baselineSavings Plans /Reserved Instancesup to ~72% offSpiky / batchfault-tolerant?use Spotup to ~90% offUnpredictableshort-lived spikesstay on-demandor serverless
The pricing-model decision: right-size first, commit steady baseline to Savings Plans or Reserved Instances, and send interruptible work to Spot.

When should you buy Savings Plans or Reserved Instances?

Once your footprint is right-sized, commitment-based discounts are the biggest structural saving on steady workloads.

7. Commit steady compute to Savings Plans

A Compute Savings Plan commits you to a dollars-per-hour spend for 1 or 3 years in exchange for discounts up to roughly 66%, and it applies flexibly across EC2, Fargate, and Lambda in any region and instance family. Buy it for your always-on baseline only — the floor of your usage graph, never the peaks. Cost Explorer's Savings Plans recommendations size this for you from the last 7, 30, or 60 days.

8. Use Reserved Instances where they still win

For RDS, ElastiCache, Redshift, and OpenSearch — which Savings Plans do not cover — Reserved Instances remain the discount lever, up to about 72% off on a 3-year term. Prefer Standard RIs for stable databases and Convertible RIs when you may change instance family. Match the term to how confident you are in the workload's next year.

How do Graviton and Spot cut compute cost further?

Beyond discounts on what you already run, you can change what you run.

9. Move to Graviton (ARM) instances

AWS Graviton processors deliver meaningfully better price-performance than comparable x86 instances — commonly 20% cheaper for equal or better throughput. For most PHP, Node, Python, Java, and containerized apps the switch is a one-line change from m6i to m7g (or t4g for burstable). Test on a canary first: rebuild any native extensions for arm64, then roll out. RDS and ElastiCache offer Graviton nodes too.

10. Send interruptible work to Spot instances

Spot instances use spare AWS capacity at up to ~90% off on-demand, with the catch that AWS can reclaim them with a two-minute warning. That is fine for anything fault-tolerant: CI/CD runners, batch jobs, data processing, and stateless web tiers behind an autoscaling group with a mixed instances policy. Pair Spot for the flexible portion with a Savings Plan for the guaranteed baseline. Our DevOps case studies show this mixed model running in production.

How does S3 lifecycle tiering reduce storage cost?

Storage is the leak that grows silently. Most objects are read constantly for a week, then almost never — yet they sit in S3 Standard forever.

11. Tier S3 with lifecycle rules and Intelligent-Tiering

S3 storage classes drop in price as access drops: Standard → Standard-IA → Glacier Instant/Flexible → Glacier Deep Archive. A lifecycle rule ages objects down automatically. If access patterns are unpredictable, S3 Intelligent-Tiering moves objects between tiers for you and removes the guesswork:

{
  "Rules": [{
    "ID": "archive-old-objects",
    "Status": "Enabled",
    "Filter": {"Prefix": "logs/"},
    "Transitions": [
      {"Days": 30,  "StorageClass": "STANDARD_IA"},
      {"Days": 90,  "StorageClass": "GLACIER"},
      {"Days": 365, "StorageClass": "DEEP_ARCHIVE"}
    ],
    "Expiration": {"Days": 730}
  }]
}

Apply it with aws s3api put-bucket-lifecycle-configuration. Also enable a rule to abort incomplete multipart uploads after 7 days — orphaned upload parts are invisible in the console but still billed.

S3 lifecycle tiering: cost falls as objects ageStandardhot, day 0Standard-IA30 daysGlacier90 daysDeep Archive 365dhighest $/GBlowest $/GBaccess frequency drops left to right — pay less for colder data
S3 lifecycle tiering ages objects from Standard down to Deep Archive, cutting the per-GB cost of data you rarely read.

What architectural change gives the biggest long-term saving?

The final tactic is structural — it changes how you pay for traffic, which is often the most opaque line on the bill.

12. Cut data-transfer and NAT Gateway costs with VPC endpoints

Data transfer is deceptively expensive: cross-AZ traffic, internet egress, and especially the NAT Gateway's per-GB processing charge. Private subnets that talk to S3, DynamoDB, ECR, or other AWS services through a NAT Gateway pay twice — the hourly NAT fee and the per-GB fee. Replace that path with VPC Gateway Endpoints (free for S3 and DynamoDB) and Interface Endpoints for other services, and keep same-AZ placement where latency-sensitive services talk to each other. Also front public content with CloudFront, whose egress is cheaper than direct S3 or EC2 egress and often lands in a lower tier. Combined, these move a large, mysterious data-transfer line down sharply.

Conclusion

Reducing your AWS bill is not one heroic move — it is a repeatable loop: measure in Cost Explorer, delete idle resources, right-size, commit the steady baseline to Savings Plans or Reserved Instances, then push variable work to Spot and Graviton and tier your storage. Run these 12 cloud cost optimization tactics once and you will typically cut 30–50% of spend; schedule them quarterly and the savings hold. If you want a fixed-scope audit that pinpoints your biggest leaks first, get in touch or see how our cloud and DevOps services put this into practice. For the deployment side of a lean stack, read our guide on building a CI/CD pipeline with GitLab CI.

Frequently Asked Questions

Start with the zero-risk wins: open Cost Explorer to find your biggest services, then delete unattached EBS volumes, unused Elastic IPs, idle load balancers, and stale NAT Gateways. These cost money with no benefit, so removing them cuts spend immediately without any performance trade-off.

Yes. Cost Explorer is free to enable and view in the AWS console. It breaks spend down by service, region, account, and resource tag, and powers right-sizing and Savings Plans recommendations. Only programmatic API calls to Cost Explorer carry a small per-request charge.

Savings Plans commit you to a dollar-per-hour compute spend and apply flexibly across EC2, Fargate, and Lambda in any region or family. Reserved Instances commit to a specific service and configuration but still cover RDS, ElastiCache, Redshift, and OpenSearch, which Savings Plans do not.

A Compute Savings Plan can cut compute cost by up to roughly 66%, and an EC2 Instance Savings Plan up to about 72%, in exchange for a one or three year commitment. Buy them only for your always-on baseline usage, never for spiky or temporary peaks.

Right-sizing means matching an instance's size to its actual utilization instead of over-provisioning. Using AWS Compute Optimizer and CloudWatch metrics, you drop instances that sit well below their CPU and memory limits to a smaller size, often halving that line item with no user impact.

Yes. AWS Graviton (ARM) instances typically deliver about 20% better price-performance than comparable x86 instances, meaning equal or better throughput for less money. Most managed-runtime and containerized apps run on Graviton with a one-line instance-type change after a quick canary test.

Use Spot for any fault-tolerant, interruptible workload: CI/CD runners, batch and data-processing jobs, and stateless web tiers behind an autoscaling group. Spot saves up to about 90% versus on-demand, but AWS can reclaim the capacity with a two-minute warning, so never run stateful or non-recoverable work on it alone.

Lifecycle rules automatically move objects to cheaper storage classes as they age — Standard to Standard-IA, then Glacier, then Deep Archive — because you rarely read old data. Each tier costs less per gigabyte, so rarely-accessed logs and backups stop paying hot-storage prices.

S3 Intelligent-Tiering automatically moves objects between access tiers based on how often they are read, with no retrieval fees for the frequent and infrequent tiers. It is ideal when access patterns are unpredictable, since it optimizes storage cost for you instead of you writing fixed lifecycle rules.

Data transfer stacks up from internet egress, cross-AZ traffic, and NAT Gateway per-GB processing charges. Private subnets reaching AWS services through a NAT Gateway pay both an hourly and a per-GB fee. VPC endpoints, same-AZ placement, and CloudFront each cut this cost.

VPC Gateway Endpoints for S3 and DynamoDB are free and let private subnets reach those services without a NAT Gateway, eliminating both the hourly NAT fee and per-GB data-processing charge for that traffic. Interface Endpoints do the same for many other AWS services for a small hourly fee.

Yes, for most workloads. gp3 is roughly 20% cheaper per gigabyte than gp2, includes a baseline of throughput and IOPS, and lets you tune performance independently of size. The migration is an in-place volume modify with no downtime and no data movement.

CloudWatch log groups default to Never Expire retention, so ingested logs accumulate storage cost indefinitely. Setting an explicit retention period, such as 30 or 90 days, on each log group caps that storage. Exporting long-term logs to S3 with lifecycle rules is cheaper still.

Yes. EBS volumes are billed for their provisioned size whether or not they are attached to a running instance, and an Elastic IP that is allocated but not associated with a running instance is billed hourly. Deleting the unused ones removes a common source of silent waste.

Review Cost Explorer at least monthly and set AWS Budgets with forecasted-overspend alerts for continuous monitoring. Run a full optimization pass — right-sizing, commitment coverage, storage tiering, and idle cleanup — quarterly, since workloads and pricing change and yesterday's right-sized fleet drifts over time.