It is rarely the storage
Why is S3 costing so much?
S3 storage is cheap enough that a large S3 bill is usually being driven by something other than the bytes you meant to store.
S3 Standard costs $0.023 per GB-month, so 10 TB is about $235. If your S3 bill is much larger than your stored volume suggests, the cause is normally one of five things: request charges from a chatty workload, internet egress, old object versions kept by versioning, incomplete multipart uploads that are invisible in the console, or data sitting in Standard that should be in a colder class.
The charges, and which one is biting
| Charge | Rate | When it dominates |
|---|---|---|
| Standard storage | $0.023 per GB-month | Large, mostly-idle data sets |
| PUT / COPY / POST / LIST | $0.005 per 1,000 | Small-object workloads, log shipping |
| GET / SELECT | $0.0004 per 1,000 | High-traffic content, unless CloudFront is in front |
| Internet egress | from $0.09 per GB | Serving files directly from S3 |
| Standard-IA storage | $0.0125 per GB-month | 30-day minimum, plus a retrieval fee |
| Glacier Instant Retrieval | $0.004 per GB-month | 90-day minimum |
| Glacier Deep Archive | $0.00099 per GB-month | 180-day minimum, hours to restore |
| Lifecycle transitions | $0.01 per 1,000 objects | Bites hard on millions of tiny objects |
us-east-1 list prices. Colder classes are cheaper per GB and add minimum durations plus retrieval charges, which is what makes them wrong for small objects.
The five usual causes
- →Incomplete multipart uploads. A failed upload leaves parts behind that are billed as storage and do not appear in the object listing. Buckets used by CI pipelines can hold years of them. A lifecycle rule to abort incomplete uploads after seven days is free, takes a minute, and is the single most satisfying S3 finding there is.
- →Versioning with no expiry. Versioning is on and there is no rule expiring non-current versions, so every overwrite keeps the old object forever. A bucket where the same files are rewritten nightly grows without its visible contents changing at all.
- →Request charges on small objects. At $0.005 per 1,000 PUTs, writing 10 million small files a month is $50 in requests to store perhaps 5 GB. Log shippers and analytics pipelines that write per-event objects are the usual offenders. Batching fixes it.
- →Egress without a CDN. Serving files straight from S3 to the internet is billed from $0.09 per GB. Putting CloudFront in front reduces the rate and, more importantly, means repeated requests are served from cache and never touch S3.
- →Everything in Standard. Intelligent-Tiering moves objects between access tiers automatically for a small monitoring fee per object, which makes it right for large objects with unpredictable access and wrong for millions of tiny ones. For predictable patterns, a plain lifecycle rule is cheaper.
Turn on Storage Lens first
S3 Storage Lens has a free tier that shows storage by bucket, by class, non-current version bytes and incomplete multipart upload bytes across the whole account. It answers the question "which of the five is it" in about a minute, and most people have never enabled it.
Put numbers on it
Frequently asked questions
How do I find incomplete multipart uploads?
They are invisible in the object list. S3 Storage Lens reports incomplete multipart upload bytes per bucket, and the CLI list-multipart-uploads shows them per bucket directly. The fix is a lifecycle rule aborting incomplete uploads after 7 days, applied to every bucket, which costs nothing.
Is Intelligent-Tiering always a good idea?
Not always. It charges a small monitoring fee per object per month, which is negligible for large objects and significant for millions of small ones. It is a good default for data lakes and backup buckets with unpredictable access. For a bucket where you know the access pattern, an explicit lifecycle rule is cheaper.
Does deleting objects reduce the bill immediately?
For Standard, yes, prorated. For colder classes, no: Standard-IA has a 30-day minimum, Glacier Instant Retrieval 90 days and Deep Archive 180 days, and deleting early is billed as if the object had stayed for the minimum. Moving data to a cold class and then deleting it two weeks later costs more than leaving it in Standard.
What about cross-region replication?
It doubles the storage cost, adds a per-GB transfer charge, and adds replication request charges. It is the right answer for genuine disaster recovery requirements and an expensive habit when it was enabled once for a bucket that no longer matters.
Keep reading
Prices checked against AWS list rates on 2 August 2026. AWS changes prices; treat every figure here as a close approximation rather than a quote.
£499 fixed. Free scan first. 20%+ found or it’s free.
The scan is read-only — a role you create and delete, no keys shared — and shows your estimated monthly saving before anyone talks about money.