Minimum Billable Object Size
also called Object Billing Floor, Small Object Floor
The size an object storage class charges for regardless of how small the object really is, which makes cheap tiers more expensive than standard storage for anything under that floor.
A team moves 400 million thumbnails, 20 KB each, from standard object storage into an infrequent-access class to save money. The storage line rises by a factor of six. Nothing is misconfigured and nothing is duplicated: the objects are smaller than the class is willing to bill for.
The published terms are explicit. S3 Standard-Infrequent Access, One Zone-IA and Glacier Instant Retrieval each have a minimum billable object size of 128 KB: smaller objects are stored faithfully and charged as 128 KB. Glacier Flexible Retrieval and Deep Archive add 40 KB of metadata charged per archived object, which for a 20 KB payload is twice the data itself.
Why it matters
The discount on the per-gigabyte rate is a fraction; the floor is a multiple. For 20 KB objects the floor inflates billed volume 6.4x, which no tier discount can recover. The resulting bill is both higher and harder to explain, because the console's object count and total size look exactly as expected while the invoice does not.
It also inverts the usual advice. Lifecycle rules that sweep everything older than 30 days into a colder tier are good practice for large objects and actively harmful for small ones, so a single blanket lifecycle policy across a mixed bucket reliably loses money on one half of it.
Implementation patterns
- Pack small objects into containers. Group them into objects of a few megabytes with a manifest of offsets and lengths, then serve individual items with ranged reads. Reads stay per-item; billing becomes per-container.
- Filter lifecycle rules by size where the provider allows it, so only objects above the floor are transitioned.
- Keep small-and-hot in standard storage, which has no size floor, no minimum duration and no retrieval charge.
- Count requests as well as bytes. Packing reduces storage and can increase per-request cost if each item is fetched separately, so compare both lines before committing.
- Model the whole lifecycle, not the resting state. Standard-IA has a 30-day minimum duration, Glacier Instant and Flexible 90 days, Deep Archive 180; deleting or re-transitioning early is charged pro rata for the remainder.
Industry example
The pattern is why large-scale data platforms treat small files as a first-class problem rather than an accident. Compaction in analytical table formats exists partly for query performance and partly because a lake of millions of tiny Parquet files pays per-object overheads on every one of them, in storage and in list and get requests. Datadog's writing on its Husky event store describes compactors merging small files in the manner of an LSM tree as a core component, not an afterthought, and the same reasoning drives the compaction jobs in every warehouse bronze layer.
Failure scenarios
- A tiering project that raises the bill, discovered a month later because the saving was forecast on bytes rather than billed bytes.
- A lifecycle rule that moves logs to archive daily and deletes them at 60 days, paying the 90-day minimum on every object for ever.
- Per-request cost swamping the storage saving after packing, in a workload that fetches single items at high rate.
- Index loss. Packed containers are useless without their manifest, so the manifest becomes a correctness dependency that needs its own backup and versioning.
- Archive metadata overhead ignored on a bucket of millions of tiny files, where the 40 KB per object exceeds the data stored.
Trade-offs
| Choose | Gains | Pays |
|---|---|---|
| Leave small objects in standard | no floor, no minimum duration, simple | the highest per-GB rate |
| Pack then tier | removes the floor; large objects suit cold tiers | an index to maintain; ranged-read complexity; rewrite cost |
| Tier small objects as they are | nothing | the floor, the minimum duration and the retrieval fee |
When not to use it
This is not an optimisation to apply by default. Below a few million small objects the entire saving is tens of pounds a month and the packing index is a permanent liability - a new failure mode, a migration, and a piece of code every future engineer must understand. For objects comfortably above the floor the concept simply does not apply, and for objects that must be individually immutable for compliance or individually addressable by a third party, packing is ruled out regardless of the arithmetic.
Interview question
Q: A bucket holds 900 million objects averaging 40 KB, and the team wants to cut storage cost. Walk me through the analysis, and tell me what you would need to know before recommending packing.
What a strong answer covers: computing billed bytes rather than stored bytes and noticing the 128 KB floor triples the volume; checking the read pattern and request rate before packing, since per-request cost can erase the saving; the minimum-duration charges on any transition; the operational cost of a manifest, including its backup and the rewrite needed when an item changes; and the alternative of simply leaving small hot objects in standard storage, which is free to implement and often close to optimal.
Quick check
Quiz: Why can moving 20 KB objects to an infrequent-access class raise the bill? They are billed as 128 KB each, a 6.4x inflation that exceeds the tier discount.
Flashcard: Two floors that make cold tiers expensive for small objects? The 128 KB minimum billable size on IA classes and the 40 KB per-object metadata charge on archive classes, plus minimum durations of 30, 90 and 180 days.