The shape
Most data is read almost entirely in the first hours of its life, then almost never. A photo, an order, a log line, a message: the access curve drops by orders of magnitude within days and then flattens into a long tail that never quite reaches zero.
Storage prices do not follow that curve on their own. By default everything sits in the class you wrote it to, so you pay hot prices forever for bytes whose read probability approached zero last March.
Tiered storage is the decision to move data down a ladder of storage classes as it cools. Each step down is cheaper per byte and worse in some other dimension, usually retrieval latency, retrieval cost, or minimum retention. The pattern is choosing the steps, choosing when something moves, and saying plainly what the move takes away.
Some examples:
- Keep the original upload, or only what you serve? A storage class question dressed as a product question.
- How long do logs stay searchable? A hot search index such as Elasticsearch, then object storage such as S3, then an archive class such as Glacier.
- Do old orders stay in the operational database? Moving them out is tiering; the "cold" tier is a warehouse.
What unifies them: you are not deciding whether to keep the data. You are deciding what you are willing to pay to get it back.
The mechanism
Three things define a tier: cost per byte, time to first byte, and any minimum you are charged regardless of actual use.
The move itself is usually a lifecycle rule the storage provider runs for you, keyed on object age. That is the easy part and it is why this pattern gets adopted casually. The parts that need thought:
The threshold should come from the access curve, not from a round number. Measure reads by object age. Then, for each age, compare two numbers. One is what you save by moving an object of that age down a step. The other is what you pay in retrieval fees to read it from down there. The age where the saving overtakes the retrieval cost is your threshold, and it is a calculation rather than a matter of taste.
Retrieval cost is per gigabyte, and it is charged on the way out. Cold tiers make storage cheap and reads expensive. A tier that is 5x cheaper to store but bills you per gigabyte on the way out is a bad trade for anything read even occasionally. The answer flips with read frequency, so a tier that is right for one class of object can be wrong for another sitting next to it.
Minimum retention is billed whether you use it or not. Cold classes typically bill a minimum number of days whether or not the object survives that long. Move something down and delete it a week later and you pay for the full minimum anyway, so tiering short-lived data actively loses money.
A photo service keeping every original, 3 MB each:
new objects per day 100M
bytes per day 100M x 3 MB = 300 TB
bytes per year 300 TB x 365 = 109.5 PB
Two options for those bytes:
hot storage ~5x the price of archive
archive storage 1x, plus a retrieval fee
and a minimum retention
Storing them for a year:
all hot = 5 units of cost
all archive = 1 unit + retrievals
Break-even on the retrieval fee alone:
if you retrieve X% of it per year, the archive
saving of 4 units is gone once
X x (retrieval fee) > 4 x (archive storage cost)
Data that is read essentially never keeps almost all of
that saving, so archive wins by roughly 5x.
Data that is read even 20% a year may not. Get the
retrieval fee from your provider and do this division
before writing the lifecycle rule.
The decisive question is not "how big is it" but
"what fraction of it gets read back, per year."What the steps are actually called
The ladder is generic and every provider names it differently, so here is the same ladder with real products on it, hottest first.
| step | what it is called | what you get |
|---|---|---|
| device cache | the browser's HTTP cache, an app's own local storage | instant and free, and you cannot take it back once it is there |
| edge cache | Cloudflare, Fastly, Akamai, CloudFront | a copy near the user, evicted on its own once it goes cold |
| memory cache | Redis, Memcached, ElastiCache, Memorystore | the fastest reads and the highest cost per byte, gone on restart |
| hot object storage | S3 Standard, Cloud Storage Standard, Azure Blob Hot | milliseconds, no retrieval fee, and the class you get by default |
| infrequent access | S3 Standard-IA, Cloud Storage Nearline, Azure Cool | as fast as hot and cheaper to keep, but you pay per GB to read |
| cold | Cloud Storage Coldline, Azure Cold | cheaper again, with a longer minimum billing period |
| archive, instant reads | S3 Glacier Instant Retrieval | archive prices with millisecond reads, at the highest retrieval fee |
| archive, with a wait | S3 Glacier Flexible Retrieval, Cloud Storage Archive, Azure Archive | you ask for the data and it arrives minutes to hours later |
| deep archive | S3 Glacier Deep Archive | the cheapest per byte anywhere, and the wait runs to hours |
| tape and offline | LTO cartridges in a vault | days, and a person has to go and fetch it |
The same ladder exists outside object storage. Elasticsearch and OpenSearch have hot, warm, cold and frozen data tiers, and the frozen one reads straight from object storage. For an operational database the cold step is usually a warehouse, Snowflake or BigQuery or Redshift, loaded from the database and queried instead of it.
Two things to look up before picking any of these, because they differ by provider and change over time. One is the retrieval fee per gigabyte. The other is the minimum number of days you are billed for, whether the object lives that long or not. Neither appears in the headline price per gigabyte, and together they decide the arithmetic above.
How to tell you have this problem
Your storage bill grows linearly with age while your traffic does not. Draw two charts over the same period, one of bytes stored and one of bytes served. Diverging lines mean you are accumulating cold data at hot prices.
Reads drop sharply as objects get older. Instrument retrievals with the object's creation date and bucket them. A steep drop is the signal that a ladder would pay; a flat line is the signal that it would not.
Nobody can say what would break if old data disappeared. That question has an answer, and finding it usually reveals that the data is kept for a specific, rare event: a re-encoding campaign, a legal request, a backfill. Those events tolerate slow retrieval, which is exactly what the cold tier charges you less for.
What it costs
Restore is a path you have never tested. The reason to keep cold data is a rare event, so the retrieval path runs rarely, which means it is broken more often than anyone expects. Restoring petabytes has a rate limit, a cost, and a duration measured in days. Test it on a schedule, or you do not actually know whether the data is still there.
Latency becomes bimodal, and callers are not ready. A read that is usually 20 ms and occasionally four hours cannot sit behind the same interface without the caller knowing. Either the API becomes asynchronous, returning a job, or somebody's timeout produces an incident.
Lifecycle rules act on age, but your reason is access. Age is a proxy. An old object that is suddenly popular gets demoted anyway and every read pays retrieval. Access-based tiering classes exist to fix this and cost a per-object monitoring fee, which only pays for itself on objects big enough that the storage saving beats it.
Deletion gets more expensive to reason about. With the same data spread across the tiers plus backups, "delete this user's data" now means deleting it in several places with different consistency and different timelines, and proving it under a legal clock.
Where it shows up in the course
| article | the form it takes there |
|---|---|
| Choosing a Database | the restore-you-never-rehearse problem, and where retention belongs once a data store outgrows one tier |
| originals are 9x the bytes of everything served and are read essentially never, so they go cold while derivatives stay hot | |
| URL Shortener | raw click events at 3 TB a day kept 90 days, against rollups small enough to keep forever |
| YouTube | source files at 2.6 PB a day, read essentially never after the first hour and impossible to recreate |
Getting it wrong
Tiering by age when the driver is access. Age is a proxy for coldness. When it is a bad proxy you pay retrieval fees on your most popular old objects.
Ignoring minimum retention. Moving short-lived data to a cold class costs more than leaving it. Check the minimum before writing the rule.
Forgetting the retrieval fee in the comparison. The storage saving is advertised; the retrieval charge is what decides how much of it you actually keep.
Never testing restore. Cold data you cannot get back on a schedule you can live with is not a backup or an archive. You are paying to store something you cannot use.
Exposing a bimodal read through a synchronous API. Make the slow path explicit. A caller that cannot tell the difference will discover it during an incident.
Tiering because there is a lot of data. Size is not the trigger. The drop in reads with age is the trigger, and a large pile of data that is read evenly should stay where it is.