Request a callbackBook a call
← All posts

AWS Cost Optimization Checklist: The 24 Line Items That Actually Move the Bill

TL;DR
  • Right-sizing is the fourth-best lever, not the first. Commitments, architecture and networking move more dollars per engineer-hour than resizing instances ever will.
  • The three line items almost nobody audits are NAT gateway data processing, cross-AZ traffic and CloudWatch Logs ingestion. All billed per gigabyte, none visible in a compute dashboard.
  • Work the checklist in order and stop when the next item costs more engineer-time than it saves. On most bills that happens around item 14.
Where a typical $20K/month AWS bill actually goes
$20Kper month
  • EC2 / ECS / EKS compute44%
  • Managed databases (RDS, Aurora, ElastiCache)18%
  • Data transfer + NAT gateways14%
  • Storage (S3, EBS, snapshots)12%
  • Observability (CloudWatch, X-Ray)7%
  • Everything else5%
This is the shape I have seen most often on mid-size AWS accounts, not an AWS-published statistic. Treat it as a starting hypothesis to test against your own Cost and Usage Report, not a benchmark. The point of the picture is the third and fifth slices. Networking and observability together are routinely a fifth of the bill. They are billed per gigabyte rather than per hour, and they show up in exactly zero of the instance-right-sizing dashboards most teams start with.

What actually cuts an AWS bill the most?

Commitments and architecture, in that order. Buying Savings Plans against steady compute and removing per-gigabyte network paths beats right-sizing on nearly every bill I have audited. Commitments apply to spend you have already proven you will incur, and networking charges compound silently.

AWS publishes the ceilings itself. EC2 Instance Savings Plans go up to 72% off on-demand, Compute Savings Plans up to 66%, and Spot up to 90% for interruptible work. Graviton instances are marketed at roughly 20–40% better price-performance than comparable x86 families. These are list-price levers available to anyone with an invoice, and none require refactoring an application.

Right-sizing matters, but it is fourth in line for a boring reason: it is per-resource work with per-resource payoff. Buying a three-year commitment is one afternoon that reprices half your compute. Resizing 60 instances is three weeks of tickets, change windows and arguments with service owners, and every new deployment quietly undoes part of it.

The rest of this post is the checklist I actually run, ordered by dollars saved per engineer-hour. If you want it run against your own invoice rather than read, that is what cloud cost optimization engagements start with, and you can sanity-check the numbers first with the cloud cost calculator.

What is the right order of operations for AWS cost work?

Measure, then commit, then re-architect, then right-size, then govern. Doing it in any other order wastes the two things you have least of: engineer attention and organisational patience for cost work. Each stage also makes the next one cheaper, which is the actual argument for the sequence.

Measuring first is not a formality. You cannot buy the right commitment without knowing your steady-state floor, and you cannot spot a networking problem without cost allocation tags and a Cost and Usage Report you can query. Turn on the CUR with resource IDs, land it somewhere queryable, and give yourself one week of data before you spend a dollar on anything else.

Committing second is the highest-leverage hour in the whole exercise. Cover the floor, the compute you are certain you will run for the next year, and leave the peak on-demand. Over-committing is the one mistake in this list that is genuinely hard to unwind, so cover 60–70% of the floor rather than 100% on the first pass.

Re-architecting third means removing whole line items rather than shrinking them: collapsing three NAT gateways to one plus VPC endpoints, moving steady per-request workloads off convenience-priced managed services, tiering S3 data that nobody has read in a year. This is where a 70% cut comes from, and it is the part of the story in how I cut a $200K/year cloud bill by more than 70% that people skip because it is harder than resizing an instance.

The levers, ranked by published ceiling
Published maximum discount vs on-demand list pricelower is better
Spot instances (interruptible workloads)AWS published ceilingup to 90%
EC2 Instance Savings Plans (3-yr, all upfront)AWS published ceilingup to 72%
Compute Savings Plans (flexible)AWS published ceilingup to 66%
Graviton vs comparable x86price-performance, not price20–40%
CloudWatch Logs Infrequent Access class$0.25/GB vs $0.50/GB50%
gp3 vs gp2 EBS volumes$0.08 vs $0.10 per GB-month20%
Published ceilings, not expected outcomes. Spot at 90% only applies to work that can survive a two-minute eviction notice, and the 72% Savings Plan number requires a three-year all-upfront commitment most seed-stage companies should not sign. The honest planning assumption on a first pass is a blended 25–40% on compute, which is still the largest single move available to you.

Which compute line items are worth touching first?

Commitments, processor architecture, and volume type, in that order, because all three reprice existing workloads without changing application code. Together they routinely take 30–45% off a compute line with no functional risk, a better trade than any right-sizing programme I have run.

On commitments, the decision that matters is coverage, not term. Look at your minimum hourly compute spend over the last 30 days, commit to roughly two-thirds of it on a one-year Compute Savings Plan, and revisit in a quarter. Compute Savings Plans are the right default for a startup because they flex across instance family, size, region and even Fargate and Lambda, which means a re-architecture next quarter does not strand the commitment.

On Graviton, the migration is genuinely cheap for anything containerised and interpreted: Node, Python, Go, Java. Build a multi-architecture image, run it on a Graviton node group behind the same load balancer, watch p95 latency for a week, then shift the fleet. The failure mode is native dependencies compiled for x86, and you find those in the first ten minutes of a build rather than in production.

On EBS, gp3 is 20% cheaper per gigabyte than gp2 ($0.08 vs $0.10 per GB-month in us-east-1, per AWS's EBS pricing page as of August 2026) and includes 3,000 IOPS and 125 MB/s of baseline throughput at no extra charge. Converting a volume is an online operation. There is no scenario in 2026 where a general-purpose gp2 volume is the correct choice, and most accounts still have dozens.

MoveEffortRiskTypical effect on the compute lineWhy teams skip it
Compute Savings Plan at 60–70% coverage1–2 hoursLow (over-commitment)15–30%Nobody wants to sign a commitment on someone else's forecast
Graviton migration for containerised services1–3 daysLow–medium10–20%Fear of native dependencies that a build would surface in minutes
gp2 → gp3 conversion1 hourVery low20% of the EBS lineIt is invisible; nobody gets paged for a volume type
Spot for CI, batch and async workers2–5 daysMedium (interruption)Up to 90% of that sliceRequires checkpointing and a drain handler
Right-sizing over-provisioned instances2–4 weeksMedium5–15%It is the one everyone starts with, and it is fourth
Cumulative saving: commit early vs wait for a perfect forecast
34,94426,20817,4728,736001236912Cumulative saving vs all-on-demand (USD)Months from today
Commit to 65% coverage in month 1Commit in month 4 after a full forecast exerciseStay entirely on-demand
Modelled on a $20,000/month bill with a 44% compute share and a 30% blended Savings Plan discount, which is $2,600 a month. Waiting three months for a better forecast costs about $7,800, more than the worst realistic over-commitment on a partial-coverage one-year plan. This is the single most common expensive mistake I see: treating a reversible 65% commitment as if it were an irreversible 100% one.

Why is networking the line item nobody audits?

Because it is billed per gigabyte by components that have no CPU graph. A NAT gateway, a cross-AZ hop and an internet egress byte all cost real money, none appear in a right-sizing report, and together they are commonly 10–15% of an AWS bill.

The NAT gateway is the clearest example. AWS charges $0.045 per hour per gateway plus $0.045 per gigabyte processed in us-east-1 as of August 2026. Three gateways for three availability zones is about $98 a month before a single byte moves. Push 10 TB a month of container image pulls, package downloads and S3 traffic through them and that is another $450. In the S3 and ECR cases, that traffic could have gone through a VPC gateway endpoint at no data-processing charge at all.

Egress to the internet is the one finance already knows about: the first 100 GB per month is free globally, then $0.09 per GB for the first 10 TB, tapering to $0.05 per GB above 150 TB. Ten terabytes of egress is roughly $920 a month. If you are serving media or large API responses directly from EC2 or S3, putting CloudFront in front changes the rate card and is usually a one-day change.

Cross-AZ traffic is the quiet one: $0.01 per GB in each direction inside a region. It sounds trivial until a chatty service mesh, a replicated cache or a Kafka cluster spreads across three AZs and moves tens of terabytes a month between them. Topology-aware routing and same-zone read replicas are free features that most clusters never turn on. The Kubernetes-specific version of this problem gets its own treatment in Kubernetes cost optimization.

Finding the per-gigabyte lines in your own bill
$ $ aws ce get-cost-and-usage \
$ --time-period Start=2026-07-01,End=2026-08-01 \
$ --granularity MONTHLY --metrics UnblendedCost \
$ --group-by Type=DIMENSION,Key=USAGE_TYPE \
$ --filter file://data-transfer-filter.json
USE1-NatGateway-Bytes 10,214 GB $459.63
USE1-NatGateway-Hours 2,190 hrs $98.55
USE1-DataTransfer-Out-Bytes 10,003 GB $891.27
USE1-USE1-AZ-DataTransfer-Out 18,400 GB $184.00
USE1-DataTransfer-Regional-Bytes 4,120 GB $41.20
networking subtotal $1,674.65 / month
Illustrative output shaped like a real Cost Explorer query. The usage-type strings are the ones AWS actually emits; the dollar figures are a worked example at published us-east-1 rates. Run this against your own account before you touch anything else. Grouping by USAGE_TYPE rather than SERVICE is the whole trick: it is the difference between seeing '$1,674 of EC2-Other' and seeing which per-gigabyte meter is running.
Checklist
The networking sub-checklist (usually 60–90 minutes of work)
  • Add S3 and DynamoDB gateway VPC endpointsNo hourly charge, no data-processing charge; pure removal of NAT gigabytes
  • Add interface endpoints for ECR, Secrets Manager, CloudWatch Logs and STSThese do have an hourly cost; check the NAT volume they displace first
  • Count your NAT gateways and ask whether every AZ genuinely needs one$32.85/month each at $0.045/hr before any data
  • Put CloudFront in front of anything serving bulk bytes to the internetDifferent rate card, and the origin fetch is often free
  • Enable topology-aware routing so chatty services prefer same-zone peersCross-AZ is $0.01/GB each way
  • Move read replicas into the same AZ as their heaviest reader
  • Check whether VPC Flow Logs are being written to CloudWatch at $0.50/GBS3 is the cheaper destination for logs you query rarely
Every item here removes a per-gigabyte meter rather than shrinking a per-hour one, which is why the savings persist through the next deployment. The flow-logs item is on the networking list rather than the observability list on purpose: it is a networking feature that quietly bills as observability, and that is exactly why it survives audits.

What do storage and logging actually cost on AWS?

More than teams expect, because both are priced per gigabyte per month forever and neither has a natural moment where somebody deletes anything. Storage decays into cost; logs accumulate into cost. Together they are typically 15–20% of a bill and close to 100% of the guilt.

S3 Standard is $0.023 per GB-month in us-east-1 as of August 2026, and S3 Glacier Deep Archive starts at $0.00099 per GB-month, a difference of more than 20x for data you are keeping purely because deleting it feels dangerous. A lifecycle policy that moves objects untouched for 90 days into a colder class is a ten-line JSON document. S3 Intelligent-Tiering does the same thing automatically for unpredictable access patterns, at a monitoring fee of $0.0025 per 1,000 objects per month, cheap for large objects and genuinely bad for billions of tiny ones.

CloudWatch Logs is the line item that surprises people most. Ingestion into the Standard log class is $0.50 per GB after the 5 GB monthly free tier, storage afterwards is $0.03 per GB-month, and Logs Insights queries cost $0.005 per GB scanned. The Infrequent Access log class is half the ingestion price at $0.25 per GB. Five hundred gigabytes a month of debug logging nobody reads is $250 a month at Standard and $125 at IA. Dropping the log level in one service is often a bigger saving than resizing its instance.

Then there is the storage nobody owns: unattached EBS volumes, snapshots of instances terminated two years ago, old AMIs, incomplete multipart uploads, and load balancer access logs with no lifecycle rule. Individually trivial, collectively four figures a month on a mature account. This is a scripted afternoon, not a project.

Storage and observability, before and after one focused week
Before
S3, single Standard class
18 TB @ $0.023 = $414/mo
CloudWatch Logs ingestion
500 GB @ $0.50 = $250/mo
EBS, all gp2
6 TB @ $0.10 = $600/mo
Unattached volumes + orphan snapshots
~$310/mo, unowned
Log retention policy
Never expire, on every group
After
S3 with a 90-day lifecycle to Glacier IR/Deep Archive
~$150/mo
CloudWatch Logs, IA class + level dropped to INFO
180 GB @ $0.25 = $45/mo
EBS, all gp3
6 TB @ $0.08 = $480/mo
Unattached volumes + orphan snapshots
$0, scripted sweep, weekly
Log retention policy
30 days hot, 400 days in S3
$1,574/mo → $675/mo · 57% off two line items that no right-sizing tool would have flagged
A worked example at published us-east-1 August 2026 rates, not a client account. The structural point holds regardless of the numbers you plug in: these are decisions about data policy, not about capacity, and they are made once and then hold. Compare that with right-sizing, which starts decaying the day after you finish.

What is the full AWS cost optimization checklist?

Twenty-four items, ordered by dollars saved per engineer-hour rather than by AWS service. Work down the list and stop when the next item costs more engineer-time than it returns. On a bill under about $30,000 a month that usually happens somewhere around item 14, and stopping there is the correct professional judgement rather than laziness.

The ordering carries an opinion worth stating plainly: everything in the first eight items is repricing or removal, and nothing in the first eight requires a service owner to agree to a change in their application. That is why they get done. Items that require negotiation get scheduled, then rescheduled, then dropped, so put them later and be honest that they may never happen.

Two items deserve a warning. Deleting unattached EBS volumes is safe right up until the volume was somebody's manual database backup, so snapshot before you delete and sweep the snapshots a month later. And moving a workload to Spot without a drain handler does not save 90%, it costs you an incident and the political capital to do any more cost work this quarter.

Run the checklist quarterly, not once. Cost work is a hygiene loop, and the single strongest predictor of whether a bill stays down is whether one named senior engineer owns it as a metric with a target. That is the same conclusion I reached the hard way and wrote up in FinOps for AI startups.

Checklist
The 24-item AWS cost optimization checklist, in execution order
  • 1. Enable the Cost and Usage Report with resource IDs and land it somewhere queryableYou cannot cut what you cannot group by usage type
  • 2. Turn on Cost Anomaly Detection and route alerts to a channel a human reads
  • 3. Tag by team, environment and service; enforce the tags in Terraform, not in a wiki
  • 4. Buy a Compute Savings Plan covering 60–70% of your steady-state floorUp to 66% off; flexes across family, size, region, Fargate and Lambda
  • 5. Convert every gp2 volume to gp320% cheaper per GB and an online operation
  • 6. Add S3 and DynamoDB gateway VPC endpointsRemoves NAT data-processing charges outright
  • 7. Delete unattached EBS volumes, orphan snapshots and unused AMIsSnapshot first, sweep the snapshots a month later
  • 8. Set an S3 lifecycle policy and abort incomplete multipart uploadsStandard is 23x the price of Deep Archive
  • 9. Drop log levels in the three noisiest services and move CloudWatch groups to the IA class$0.50/GB → $0.25/GB, plus less of it
  • 10. Set a finite retention on every CloudWatch log group; ship long-tail logs to S3
  • 11. Audit NAT gateway count and consolidate where AZ isolation is not a real requirement
  • 12. Move containerised services to Graviton node groups20–40% better price-performance, one multi-arch build
  • 13. Put CloudFront in front of anything serving bulk bytes to the internet
  • 14. Shut down non-production environments outside working hoursA 12/5 schedule is a 64% cut on that slice
  • 15. Move CI, batch and async workers to Spot with drain handlingUp to 90%, but only with checkpointing
  • 16. Right-size the top 20 instances by cost, then stopThe long tail is not worth the tickets
  • 17. Enable topology-aware routing and co-locate chatty services in one AZCross-AZ is $0.01/GB each direction
  • 18. Review RDS and ElastiCache instance classes and Multi-AZ necessity per environmentMulti-AZ in staging is a donation
  • 19. Replace per-request managed services on steady workloads with reserved computeConvenience pricing is 5–20x raw compute at scale
  • 20. Consolidate accounts under one payer so commitments and volume tiers pool
  • 21. Move S3 replication and DR copies to a cheaper class or a cheaper region
  • 22. Audit third-party SaaS billed through AWS Marketplace against actual usage
  • 23. Add Infracost or an equivalent cost check to pull requestsFree tier covers 1,000 CI runs a month
  • 24. Give one named senior engineer the bill as a quarterly metric with a targetThe only item on this list that makes the other 23 repeat
Items 1–8 are roughly one engineer-week and typically return the largest share of the total. Items 15–19 are where a bill goes from 'tidied' to 'restructured' and where you need a service owner's cooperation. Item 24 is the only one that determines whether you are doing this again next August.

When is AWS cost optimization not worth doing?

When the bill is under roughly $2,000 a month, when you are three weeks from a fundraise or a launch, or when the engineer you would assign is the same person your roadmap depends on. In all three cases the honest answer is to turn on billing alerts, buy nothing, and revisit in a quarter.

The arithmetic is unsentimental. A serious first pass is one to two engineer-weeks. At a $150,000 loaded annual salary that is roughly $2,900–$5,800 of cost. On a $2,000-a-month bill, a very good 40% cut saves $800 a month, so you pay it back in four to seven months. But only if nothing regresses and only if the engineer had nothing more valuable to do, and at that stage of company they always do.

There is a second case that gets less airtime: when the bill is large but the growth rate is larger. If you are doubling infrastructure every quarter, a three-year commitment locks you to an architecture you will have outgrown by month nine, and time spent tuning today's topology is time not spent on the one that has to hold next year. Cover a conservative floor with a one-year plan, fix the per-gigabyte meters, and defer everything else.

I say all of this knowing it costs me engagements. It also happens to be the reason the ones I do take work: cost work has a real and finite return, and pretending otherwise is how consultants end up optimising a bill that should simply have been ignored for two more quarters.

Should you run a cost programme this quarter?
Is a serious AWS cost optimization pass worth doing right now?
Bill under $2,000/month
No, set alerts and move on

A 40% cut is $800/month against one to two engineer-weeks of cost. It pays back, slowly, in exchange for the attention of the person you can least afford to borrow.

$2,000–$20,000/month, stable architecture
Yes, items 1 through 14

One focused engineer-week returns 25–40% on most bills of this shape, and the commitments and lifecycle policies keep paying after the week ends.

Over $20,000/month
Yes, and give it an owner

At this size the whole list clears its cost several times over, and item 24, a named owner with a target, is what stops the bill drifting back within two quarters.

Infrastructure doubling every quarter
Partial: floor commitments and per-GB meters only

Do not sign a three-year plan against an architecture with a nine-month half-life. Fix NAT, egress and logging, which stay true through a rewrite.

Three weeks from a launch or a raise
No, defer it

Every item on this list is a change, every change is a risk, and the expected value of not being down during your launch week exceeds any plausible saving.

Two of the five branches say no or not yet. That distribution matches what I actually tell people on calls, and it is the reason I would rather publish the decision tree than a landing page promising everyone 70%.

What did this look like when I actually ran it?

I cut an equivalent $200K-per-year enterprise cloud bill by more than 70% and did the underlying GCP to Azure and AWS migration solo, with zero downtime. The savings did not come from right-sizing. They came from credits, from replacing per-request managed services, and from putting each workload where its pricing was actually best.

The largest single lever was one most checklists cannot include, because it is not a setting: $300K in cloud credits, secured across Microsoft for Startups and AWS Activate. That is a pitch, not a form, and I wrote up exactly how it works in how to get cloud credits for startups. The second largest was moving steady, predictable workloads off per-request billing, where convenience is priced at a large multiple of raw compute.

The organisational half mattered as much as the technical half. Cross-training the team removed the need for a dedicated DevOps function, and engineering spend went from $60K to $12K a month. I mention it because a cost programme that ends when the consultant leaves is not a cost programme, and ownership is the thing that persists.

What I would do differently: instrument first, and tag from day one. I spent longer than I should have reconstructing which team owned which line item, and every hour of that was an hour not spent cutting. Item 1 and item 3 on the checklist above exist because I did them fourth.

AWS cost optimization: common questions

What is the fastest way to reduce an AWS bill?

Buy a Compute Savings Plan covering 60–70% of your steady-state compute floor. It takes about an hour, requires no application change, and AWS publishes discounts of up to 66% for Compute Savings Plans and 72% for EC2 Instance Savings Plans. Convert gp2 volumes to gp3 in the same session for another 20% off the EBS line.

How much can you realistically save on AWS?

A first serious pass typically returns 25–40% on a bill that has never been audited, and more if credits or an architectural change are available. Reductions above 60% almost always involve removing whole line items (per-request managed services, NAT data processing, hot log retention) rather than shrinking existing ones.

What does an AWS NAT gateway actually cost?

In us-east-1 as of August 2026, $0.045 per hour per gateway plus $0.045 per gigabyte processed. That is about $32.85 a month per gateway before any traffic, so three availability zones cost roughly $98 a month idle. Ten terabytes of processed data adds a further $450, much of which S3 and DynamoDB gateway endpoints remove entirely at no data-processing charge.

Is right-sizing EC2 instances worth the effort?

Yes, but it is the fourth-best lever, not the first. Right-sizing is per-resource work with per-resource payoff and it decays with every deployment, whereas commitments, Graviton and volume-type changes reprice existing workloads in hours. Right-size the top 20 instances by cost and leave the long tail alone.

How much does CloudWatch Logs cost and how do you reduce it?

Standard class ingestion is $0.50 per GB after a 5 GB monthly free tier, storage is $0.03 per GB-month, and Logs Insights queries cost $0.005 per GB scanned. The Infrequent Access class halves ingestion to $0.25 per GB. The larger lever is producing less: dropping debug logging in the noisiest services usually beats any pricing change.

When should a startup not bother optimizing its AWS bill?

Below roughly $2,000 a month, or within three weeks of a launch or fundraise, or when the only available engineer is the one your roadmap depends on. A serious pass costs one to two engineer-weeks; on a small bill a strong 40% cut saves $800 a month and pays back in four to seven months, which rarely beats shipping.

Ready to talk numbers?

Twenty minutes, straight to the engineer. No sales rep, no deck.