AWS costs: S3 request pricing - when storage is cheap but touching it is not

Logeshwaran.C

Amazon S3 storage looks cheap because the sticker price is the part everyone reads: $0.023 per GB a month for S3 Standard. But every PUT, COPY, POST, LIST, and GET you send is billed separately, per 1,000 requests, and that meter runs whether you touch the console, run a script, or let an app sync in the background. The counterintuitive part: the storage classes marketed as "even cheaper" charge more per request, not less — so a bucket full of small, frequently-touched files can cost more in Glacier than it did in Standard, even though the per-GB storage rate dropped.

⚡ Quick Answer

S3 Standard request rates → PUT/COPY/POST/LIST: $0.005 per 1,000 requests. GET/SELECT and everything else: $0.0004 per 1,000 requests. DELETE and CANCEL: free.

The trap → cheaper storage classes (Standard-IA, One Zone-IA, the Glacier tiers) charge more per request and per retrieval, plus a minimum storage duration. Millions of small, frequently-read objects can cost more once "optimized" than they did in Standard.

One line if you only read this box: count your requests before you move storage classes, not after. Full math is in the worked example and the lifecycle trap below.

What S3 request pricing actually charges you for

Amazon S3's bill has three main pillars: storage (what you keep), requests (what you do to it), and data transfer (what leaves it). Most people budget for the first one and forget the second exists until it shows up. Every API call you make against a bucket — uploading an object, listing a folder, reading a file, running a lifecycle transition — is a metered request, and Amazon bills for it whether the call comes from your own code, a third-party backup tool, or you clicking around in the AWS Management Console. Browsing your own bucket in the console generates the same GET and LIST charges as if a script did it; there's no "human discount."

S3 groups requests into two price bands. PUT, COPY, POST, and LIST requests — the ones that write data or ask S3 to enumerate what's in a bucket — are billed at one rate. GET, SELECT, and "all other" requests — the ones that read data back — are billed at a lower rate. DELETE and CANCEL requests don't cost anything at all, which is worth remembering the next time someone tells you cleaning up old files will run up your bill; it won't, not directly.

‍♂️ Jake's Reality Check

"I moved my repair-photo backups to S3 because storage was cheaper than my old NAS. Then the bill had a line item called 'Requests' that was bigger than the storage line. Did I get billed for looking at my own files?"

Yes, technically. Every time your backup app checks whether a photo already exists, that's a request. Every time it lists the folder to see what's new, that's a request. None of it shows up as a separate warning — it's just baked into the same invoice as storage, one line down.

S3 Standard request pricing, in full

Here's the published request pricing for S3 Standard, the default storage class most buckets use:

Request type Price (S3 Standard) What triggers it
PUT, COPY, POST, LIST $0.005 per 1,000 requests Uploading an object, copying it, listing a bucket or folder
GET, SELECT, and all other requests $0.0004 per 1,000 requests Downloading or reading an object, running an S3 Select query
DELETE, CANCEL Free Removing an object, canceling a multipart upload

Two details in that table catch people out. First, LIST requests are billed at the same rate as PUT/COPY/POST — a folder listing costs the same as an upload, which surprises people who assume "just looking" is closer to a GET. Second, a COPY request is a write, not a read, because S3 has to create a new object; if your pipeline copies objects between buckets as part of a workflow, that's PUT-rate pricing on both the read side of the source data movement and a full write on the destination.

The 12.5x gap between writes and reads

Do the ratio: $0.005 versus $0.0004 works out to writes costing roughly 12.5 times more than reads, per request. For a typical read-heavy website or app — users mostly downloading images, videos, or files — that ratio works in your favor, because GETs dominate the request count but sit on the cheap side of the meter. It flips hard for write-heavy workloads: log ingestion, IoT telemetry, anything that uploads small files constantly. Ten million PUT requests costs $50. Ten million GET requests costs $4. Same request count, more than 12 times the bill, purely because of which side of the meter you're on.

Why "cheap storage" and "expensive to touch" aren't a contradiction

Amazon's own documentation is blunt about the logic here: request and ingest charges apply any time you use PUT, COPY, or a lifecycle rule to move data into a storage class — and AWS explicitly tells customers to weigh that ingest cost before moving objects anywhere, not after. The pricing design isn't an accident. S3 Standard is priced to be cheap to store and cheap-ish to access, because it's meant for data you touch often. The colder classes — Standard-Infrequent Access, One Zone-IA, and the Glacier family — are priced the opposite way: the storage rate drops the further down you go, but the request price and the per-GB retrieval charge climb, and a minimum storage duration gets bolted on (30 days for the IA classes, 90 days for Glacier Instant Retrieval and Glacier Flexible Retrieval, 180 days for Glacier Deep Archive). Delete or move an object before that window closes and you still pay for the rest of the minimum period, pro-rated.

That's the whole trade, stated plainly: Amazon isn't charging you twice for the same thing. It's pricing each class for a specific access pattern, and the request meter is how it enforces that pattern. Store something in Glacier and touch it constantly, and the request and retrieval charges will eat the storage savings alive. Store something in Standard and never touch it, and you're paying a storage premium for access you're not using.

✅ Why this is the one to check first

Before choosing a storage class, estimate your monthly request count for that data, not just its size. A cheaper storage tier with a request pattern that doesn't fit it is not a savings — it's a different bill with a different shape.

The three ways request costs quietly take over a bill

Individually, $0.005 per 1,000 requests looks like nothing. It becomes something in three specific ways.

1. Volume from automation, not from people

Humans don't generate millions of requests by clicking around. Automated systems do: a sync client that lists a folder every few seconds to check for changes, a Lambda function triggered on every object upload, a backup job that verifies every file's existence before writing it. None of these feel expensive individually. At scale, they're the entire bill.

2. Small objects instead of few large ones

Request pricing is per-request, not per-byte. Uploading one 10 GB file is one PUT. Uploading ten thousand 1 MB files to represent the same 10 GB is ten thousand PUTs. Workloads that chop data into many small objects — log shipping, IoT sensor readings, thumbnail generation — pay the request meter far more per gigabyte stored than workloads that write in bulk.

3. Mismatched storage class and access pattern

This is the one covered above, and it's the one that costs the most per incident because it compounds: every read against archival storage, for as long as the mismatch lasts, pays the higher rate plus a retrieval charge that Standard doesn't have at all.

How the request price changes as storage gets cheaper

Amazon publishes eight storage classes today, and the shape of the trade-off is consistent across all of them: as the per-GB storage price drops, the price to write into that class, read from it, and the minimum time you're committed to keeping data there, all rise. S3 Intelligent-Tiering is the deliberate exception — no retrieval charge and no minimum storage duration at all, because it's designed to move objects between access tiers automatically as their access pattern changes, and Amazon doesn't want to penalize the auto-tiering it's doing on your behalf.

Storage class Minimum storage duration Retrieval charge Request price vs. Standard
S3 StandardNoneNoneBaseline
S3 Intelligent-TieringNoneNone (any tier)Same as Standard, plus a small per-object monitoring fee
S3 Express One Zone1 hourPer GB retrievedLower than Standard — built for high request rates
S3 Standard-IA30 daysPer GB retrievedHigher than Standard
S3 One Zone-IA30 daysPer GB retrievedHigher than Standard
S3 Glacier Instant Retrieval90 daysPer GB retrievedHigher still
S3 Glacier Flexible Retrieval90 daysFree bulk retrievals; paid for faster tiersHigher on writes; retrieval speed is minutes to hours
S3 Glacier Deep Archive180 daysPer GB, restore in 12+ hoursHighest write cost, lowest storage cost

The exact current dollar figures for each class's per-1,000-request rate move with pricing updates, so check the live S3 pricing page for the number that applies to your Region right now rather than trusting a screenshot from a year-old blog post — this is exactly the kind of number that's worth re-verifying before it goes into a spreadsheet someone will use for budgeting.

The two archive-tier storage classes also carry a metadata overhead most people never budget for: S3 Glacier Flexible Retrieval and S3 Glacier Deep Archive each charge for roughly 40 KB of extra metadata per archived object — 32 KB billed at the archive class's own rate and 8 KB billed at Standard rates — so you can still list every object in the bucket without restoring it first. If you're archiving millions of very small objects, that overhead alone can rival the size of the objects themselves.

The console tax: browsing your own bucket isn't free

Amazon's documentation says this outright: browsing storage through the S3 console generates GET, LIST, and other requests to facilitate the browsing, and they're charged at the exact same rate as requests made through the API or an SDK. To provide a smoother experience, the console sometimes proactively fires off more than one request per action you take, and some interactive operations translate into several requests behind the scenes. Clicking through a folder tree with thousands of subfolders, refreshing a bucket listing repeatedly while you look for a file, or leaving a console tab open on auto-refresh all cost real money — just not enough, individually, for anyone to notice on a small bucket.

The requests nobody budgets for

A handful of request types don't show up in most people's mental model of "using S3" at all:

  1. Lifecycle transitions. When a lifecycle rule moves an object from Standard to Standard-IA, or from Standard-IA to Glacier, that move is billed as a request against the destination class — on top of whatever it cost to store the object in the first place. Millions of objects transitioning on the same day generate millions of billed requests in one shot.
  2. Multipart upload parts. Objects over 100 MB are recommended to go through multipart upload, and each part uploaded is its own PUT request. A single 5 GB file split into fifty 100 MB parts is fifty PUTs, not one.
  3. Replication PUTs. Cross-Region and Same-Region Replication write a copy of every replicated object to the destination bucket, and each copy is a full PUT request at the destination class's rate, plus inter-Region data transfer if the destination is in a different Region.
  4. Restore requests from archive tiers. Pulling an object out of Glacier Flexible Retrieval or Deep Archive is its own billed operation, separate from the GET you'll make afterward to actually read the restored copy.
  5. "Standard and bulk" retrievals in Intelligent-Tiering are free across all five of its access tiers — but if you call a second restore on an object that's already being restored, that follow-up call is billed as an ordinary GET request, not as a free retrieval.

None of these are hidden fees in the sense of being undisclosed — they're all in the documentation. They're hidden in the sense that nobody reads the documentation before flipping on a lifecycle policy, and the first time most people learn a transition has a request cost is when the bill for the month it ran is larger than expected.

A worked example: two buckets, same storage, different bills

Say you're storing 500 GB in S3 Standard, US East (N. Virginia). At $0.023 per GB for the first 50 TB tier, storage alone is $11.50 a month. Now add two very different request profiles to the same 500 GB.

Bucket A: a photo backup, written once and rarely read

50,000 PUTs a month (initial uploads), 5,000 GETs (occasional retrieval when someone needs an old photo). PUT cost: 50,000 ÷ 1,000 × $0.005 = $0.25. GET cost: 5,000 ÷ 1,000 × $0.0004 = $0.002. Total requests: about 25 cents. Storage dominates completely.

Bucket B: an IoT ingestion pipeline writing constantly

20 million PUTs a month from small sensor-reading files, 40 million GETs from a dashboard reading them back. PUT cost: 20,000,000 ÷ 1,000 × $0.005 = $100. GET cost: 40,000,000 ÷ 1,000 × $0.0004 = $16. Total requests: $116 — ten times the storage cost, on the exact same 500 GB footprint.

Same region, same storage class, same 500 GB. One bucket's bill is 98% storage. The other's is 91% requests. The byte count told you nothing about which one would be expensive; the access pattern told you everything.

⚠️ What this actually breaks

A cost estimate built only from "how many gigabytes will I store" will be wildly wrong for anything write-heavy or read-heavy at high volume. If your workload makes more than a few million requests a month, model the request line separately — don't fold it into a rough storage guess.

Six ways to cut request costs without deleting anything

Cheapest and least disruptive first.

  1. Batch small writes into fewer, larger objects. If your pipeline is currently writing thousands of tiny files, combining them before the PUT — even something as simple as writing one log file per hour instead of one per event — collapses the request count by orders of magnitude for the same total bytes.
  2. Cut unnecessary LIST calls. Applications that poll a bucket by listing its contents on a timer are trading a cheap idea for an expensive habit. S3 Event Notifications (to EventBridge, SNS, SQS, or Lambda) tell your application when something new lands, so it never has to ask.
  3. Cache what you read repeatedly. If the same objects are fetched over and over by the same application, a cache in front of S3 — even something simple in your application layer — turns a thousand GETs into one GET and 999 cache hits. Amazon CloudFront in front of a bucket accomplishes the same thing for public content, and data transferred out to CloudFront doesn't incur the internet data-transfer charge either.
  4. Right-size multipart upload part sizes. Multipart uploads exist to make large-object uploads resilient and parallel, but splitting a file into more, smaller parts than necessary multiplies PUT requests for no benefit. Larger part sizes for large files mean fewer billed parts.
  5. Use Intelligent-Tiering for data you can't predict. If you genuinely don't know whether an object will be read again next week or never, Intelligent-Tiering removes the guesswork: no retrieval charge, no minimum duration, and the storage cost drops automatically as access patterns shift, for a small per-object monitoring fee.
  6. Move only what you're sure about into archive tiers, and move it deliberately. Lifecycle rules are convenient, but a rule that transitions everything in a prefix after 30 days, applied to a prefix that still gets read occasionally, will generate ongoing retrieval charges that erase the storage savings. Scope lifecycle rules narrowly, based on real access logs, not a guess.

✅ Why this is the one to use

Of the six, batching small writes and cutting LIST polling deliver the biggest reduction for the least engineering effort, because they attack request count directly rather than shuffling which storage class absorbs the cost.

When moving to cheaper storage costs you more than it saves

This is the scenario the whole article is really about, so it's worth spelling out plainly: a lifecycle rule that transitions an object from S3 Standard to Glacier Flexible Retrieval after 30 days looks like pure savings on paper — the storage rate drops sharply. But that transition is itself a billed request against the Glacier tier, the object is now locked into a 90-day minimum storage duration (leave before that and you pay the remaining days anyway), and every future read costs a per-GB retrieval fee that Standard never charged at all. If the access pattern for that data was "read a few times a month, forever," the object was cheaper to leave in Standard, full stop — the storage line would have been higher, but the total bill lower.

The honest rule: lifecycle policies save money for data whose access frequency genuinely drops over time — old backups, completed project files, logs past their retention window. They cost money when applied blanket-wide to a bucket without checking whether the objects inside it are actually going cold.

The two classes built for high request volume

S3 isn't only a lesson in what not to do — two of its storage classes exist specifically to make high request volume cheaper, not more expensive.

S3 Intelligent-Tiering automatically watches access patterns per object and moves data between a Frequent Access tier, an Infrequent Access tier (after 30 consecutive days with no access), and an optional Archive Instant Access tier (after 90 days), with no retrieval charge at any step and no minimum storage duration on the class as a whole. It's the answer for data where you genuinely don't know the access pattern in advance — new applications, data lakes, user-generated content — because it removes the guessing game this whole article has been about.

S3 Express One Zone goes the other direction: it's built for workloads that need very high request rates and consistent single-digit-millisecond latency, and Amazon states it can reduce request costs by up to 80% compared to S3 Standard for the workloads it targets, in exchange for storing data in a single Availability Zone instead of the usual three.

 What changed between versions

  • Before: S3 Express One Zone launched with storage at $0.16 per GB-month, PUT requests around $0.0025 per 1,000, and GET requests around $0.0002 per 1,000.
  • Now: effective April 10, 2025, Amazon cut storage to $0.11 per GB-month (31% lower), PUT requests to $0.00113 per 1,000 (55% lower), and GET requests to $0.00003 per 1,000 (85% lower) — plus a 60% cut to the per-GB upload and retrieval charges, now applied to all bytes transferred rather than only the portion above 512 KB.
  • What that means: if you evaluated Express One Zone before mid-2025 and decided it wasn't worth the single-AZ trade-off, the math has meaningfully shifted since then.

How to see request costs before the bill arrives

The AWS Pricing Calculator lets you model storage, requests, and data transfer together before you build anything, which is the cheapest way to catch a request-heavy design on paper instead of on an invoice. Once a workload is live, AWS Cost Explorer breaks S3 charges down by usage type, so request costs show up as their own line rather than blending into "S3" as a single number. For deeper visibility into which buckets and prefixes are generating the requests, S3 Storage Lens provides activity metrics — including request counts — at the account, bucket, or prefix level, for a separate monthly charge if you use the advanced metrics tier.

Edge cases: replication, versioning, and multi-account access

A few situations change the request math in ways that aren't obvious from the basic pricing table.

Versioning. Enabling S3 Versioning means every overwrite of an object creates a new version rather than replacing the old one — each new version is billed as its own PUT, and every version that exists continues to accrue its own storage charge until it's explicitly deleted, even after it's no longer the "current" version a normal GET would return.

Replication. Cross-Region Replication and Same-Region Replication both bill a PUT request at the destination for every object replicated, on top of the storage charge for the replica and — for Cross-Region Replication specifically — inter-Region data transfer out of the source bucket. Replicating a bucket that receives millions of small writes a month effectively doubles that bucket's PUT request bill.

Cross-account and Requester Pays access. Normal S3 pricing applies when another AWS account accesses your bucket — you, the bucket owner, pay the request and transfer charges by default. If you want the requester to cover those costs instead, S3 supports configuring a bucket as Requester Pays, which shifts request and download charges to whoever is making the call.

Free tier, and where data transfer fits in

New AWS accounts created on or after July 15, 2025 receive up to $200 in Free Tier credit, usable across eligible services including S3, available on the free plan for six months and usable within twelve months of account creation. Accounts created before that date keep the older, service-specific free tier: 5 GB of S3 Standard storage, 20,000 GET requests, 2,000 PUT requests, and 100 GB of data transfer out per month, for the account's first year.

Data transfer is the third pillar of the bill and worth a paragraph here because it's easy to conflate with request pricing. Data transferred into S3 from the internet is always free, no matter the volume. Data transferred out to the internet is free for the first 100 GB a month, aggregated across all AWS services and Regions combined — not 100 GB per service. Beyond that free allowance, the published rate for the first tier of usage runs $0.09 per GB in most commercial Regions, stepping down at higher volume tiers. Data moved between S3 and another AWS service in the same Region, or out to CloudFront, doesn't incur this charge at all.

Ethan's take: stop optimizing storage first

Jake asked Ethan, once the bill from Bucket B in the example above landed on a real client's account, why nobody had warned them the storage class they'd been told to use for "savings" was the wrong shape for a dashboard that refreshed every few seconds.

"Because everyone starts the conversation with storage," Ethan said. "It's the number on the pricing page with the most digits after the decimal, so it feels like the one to shrink. Requests are the one that actually moves for a workload like yours, and it's also the one nobody looks at until the invoice makes them. My rule is: model requests before you touch storage class. If the request count is small, use whatever class matches your retention needs and don't overthink it. If the request count is large, that number picks the storage class for you — usually toward Standard or Intelligent-Tiering, not away from them."

‍♂️ Jake's Reality Check

"So the 'cheap' storage tier isn't a mistake AWS is hoping I make. It's just priced for a different job than the one I gave it."

Exactly right. Nothing in this pricing model is deceptive — it's all published and consistent. The cost only surprises you when the storage class and the access pattern don't match.

Frequently asked questions

Does browsing a bucket in the AWS console cost money?

Yes. Browsing generates GET, LIST, and other requests at the same rate as API or SDK calls, and the console sometimes fires more than one request per action to keep the interface responsive.

Are DELETE requests free in every S3 storage class?

Yes, DELETE and CANCEL requests are free across all S3 storage classes. Deleting an object never itself generates a request charge, though deleting it before a class's minimum storage duration ends can trigger a pro-rated early-deletion storage charge.

Why is a LIST request billed at the PUT rate instead of the GET rate?

Amazon bills LIST requests, for any storage class, at the same rate as PUT, COPY, and POST requests — not at the lower GET rate many people assume applies to "read-only" operations like listing.

Does a COPY request count as a read or a write for billing?

A COPY is billed as a write, at the PUT/COPY/POST/LIST rate, because it creates a new object at the destination even though it reads from a source.

Do lifecycle transitions cost anything beyond the new storage rate?

Yes. Moving an object between storage classes — whether by a lifecycle rule or manually — is billed as a request against the destination storage class, in addition to whatever the object's new storage rate becomes going forward.

What is a minimum storage duration, and which classes have one?

It's a minimum billing period AWS applies once an object lands in certain storage classes: 30 days for S3 Standard-IA and One Zone-IA, 90 days for S3 Glacier Instant Retrieval and Glacier Flexible Retrieval, and 180 days for S3 Glacier Deep Archive. Deleting, overwriting, or transitioning an object out early still bills the remaining days in that minimum. S3 Standard, Intelligent-Tiering, and Express One Zone (which uses a 1-hour minimum) don't carry this multi-day commitment.

Is S3 Intelligent-Tiering always the safest default choice?

It's a strong default when you genuinely don't know an object's future access pattern, because it carries no retrieval charge and no minimum storage duration across its access tiers. It's not automatically the cheapest option for data whose access pattern you already know with confidence — for that data, picking the matching class directly usually beats paying Intelligent-Tiering's small per-object monitoring fee.

How much does restoring an object from Glacier cost?

Restoring from S3 Glacier Flexible Retrieval or Glacier Deep Archive is billed as part of the restore request, and while the restored copy is temporarily accessible, it's charged at S3 Standard storage rates for the duration you choose to keep it available, on top of the ongoing archive-tier storage charge for the original.

Do S3 Event Notifications cost anything to set up?

There's no additional S3 charge for configuring event notifications themselves. You do pay the normal pricing for whichever downstream service delivers or processes the notification — Amazon SNS, Amazon SQS, or AWS Lambda.

Does enabling S3 Versioning increase my request bill?

Yes, indirectly. Each overwrite creates a new object version, and each new version is billed as a PUT request, plus its own ongoing storage charge, on top of whatever versions already exist for that key.

Does S3 Cross-Region Replication double my request costs?

It adds a PUT request at the destination Region for every object replicated, plus inter-Region data transfer out from the source. For a bucket with heavy write traffic, replicating it meaningfully increases the total PUT request bill, not just the storage bill.

Is data transfer into S3 ever charged?

No. Data transferred into Amazon S3 from the internet is always free, regardless of volume or storage class.

Does the 100 GB free data transfer allowance apply separately to every AWS service?

No. The 100 GB of free monthly data transfer out to the internet is aggregated across all AWS services and Regions on the account, not granted separately per service.

Can I make another AWS account pay for requests against my bucket?

Yes, by configuring your bucket as a Requester Pays bucket. Once enabled, the requester covers the cost of requests and downloads instead of you, the bucket owner.

Why does S3 Express One Zone have lower request prices than S3 Standard?

Express One Zone is purpose-built for high-request-rate, low-latency workloads, and Amazon states it can reduce request costs by up to 80% compared with S3 Standard for the workloads it's designed around, in exchange for storing data in a single Availability Zone rather than a minimum of three.

How do I see how many requests my bucket is actually generating?

AWS Cost Explorer breaks S3 charges down by usage type so request costs appear as a distinct line item, and S3 Storage Lens provides activity metrics, including request counts, at the account, bucket, or prefix level for closer diagnosis.

Also Read:

AWS costs: The NAT gateway bill - the $32/month nobody planned

 AWS costs: Data transfer pricing - the map of what is free and what is not

 AWS costs: CloudWatch Logs ingestion - the log bill that outgrew the app

 AWS costs: Cross-AZ traffic - the invisible cent per gigabyte

 AWS costs: Unattached Elastic IPs and idle load balancers - the standing waste list

AWS costs: S3 request pricing - when storage is cheap but touching it is not

AWS costs: S3 storage classes decided honestly - IA, Glacier, Intelligent-Tiering

AWS costs: Glacier retrieval - the bill for wanting your data back

Revision note. Written September 2026, covering S3 Standard, Intelligent-Tiering, Express One Zone, the Standard-IA and One Zone-IA classes, and the three Glacier storage classes as currently published by AWS. Exact per-class request rates and free-tier terms are the kind of number AWS revises without much fanfare, so if this page is more than a few months old when you're reading it, cross-check the live S3 pricing page before you commit a budget to it. If you're staring at a surprise request line right now, you're not the first person this has happened to, and it usually traces back to one storage class doing a job it wasn't priced for — that's fixable.

Related