How do Elasticsearch's hot, warm, cold and frozen data tiers differ in what they store and cost?
answer
- Node roles, cheapest hardware last
- Writes only ever hit the first one
- Read-only data can be merged and de-replicated
- One tier keeps a snapshot as its second copy
- The last one keeps only a local cache
basics
~20 sHot holds the actively written, most-queried indices on the fastest hardware. Warm holds recent read-only data on cheaper nodes, cold trades replicas for snapshot-backed storage, and frozen keeps only a local cache while the data itself lives in object storage.
solid answer
~50 sThe tiers are node roles — `data_hot`, `data_warm`, `data_cold`, `data_frozen`, plus `data_content` for non-time-series indices — assigned to nodes with progressively cheaper hardware. An index sits on a tier because of `index.routing.allocation.include._tier_preference`, and ILM's `migrate` action rewrites that setting as the index enters each phase. **Hot** takes the writes and the recent queries: fast disks, most RAM, normal replica counts. **Warm** holds read-only indices that are still queried directly from local disk on cheaper nodes, usually force-merged and often with fewer replicas. **Cold** typically mounts the index as a fully mounted searchable snapshot, so a repository copy provides redundancy and local replicas can be dropped. **Frozen** goes further: a partially mounted searchable snapshot where only a bounded local cache exists and blocks are fetched from object storage on demand — enormous retention for very little disk, at the cost of much slower first queries.
code
json · 35 lines// PUT _ilm/policy/logs-13m
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": { "max_primary_shard_size": "50gb", "max_age": "1d" }
}
},
"warm": {
"min_age": "7d",
"actions": {
"forcemerge": { "max_num_segments": 1 },
"set_priority": { "priority": 50 }
}
},
"cold": {
"min_age": "30d",
"actions": {
"searchable_snapshot": { "snapshot_repository": "logs-repo" }
}
},
"frozen": {
"min_age": "90d",
"actions": {
"searchable_snapshot": { "snapshot_repository": "logs-repo" }
}
},
"delete": {
"min_age": "395d",
"actions": { "delete": {} }
}
}
}
}go deeper
Recall the progression from hot through warm and cold to frozen, that only hot takes writes, and that each step trades query speed for cheaper storage.
Explain that tiers are node roles driving an allocation preference, how ILM's migrate action rewrites it per phase, and that min_age is cumulative from rollover rather than per-phase.
Be ready to justify each transition on cost — force merge and fewer replicas in warm, snapshot-backed redundancy in cold, cache-only storage in frozen — and to say what query latency each tier commits you to.
Own the tiering strategy across the fleet: how many tiers are worth operating, the licensing and object-storage costs they imply, and how retention promises to auditors and on-call engineers translate into hardware you have to buy.
## Tiers are node roles, not a separate feature A data tier is simply a set of nodes carrying a particular role: `data_hot`, `data_warm`, `data_cold`, `data_frozen`, and `data_content` for indices that are not time-series at all (a product catalogue, a user directory). A node may hold several of these roles; a small cluster often has one node holding all of them, which is why tiering works logically even before anyone buys different hardware. An index lands on a tier through the setting `index.routing.allocation.include._tier_preference`, which holds an ordered, comma-separated preference such as `data_warm,data_hot`. Allocation walks the list and uses the first tier that has nodes available, which is what stops an index from becoming unassigned in a cluster that has no warm nodes yet. New data-stream backing indices default to a hot preference; ordinary indices default to the content tier. ## What each tier is for **Hot.** The write index and the newest generations live here. This is where indexing throughput, refresh, translog writes and merges all happen, so it wants the fastest storage and the most memory. Queries here are the ones users run constantly — "the last 24 hours" — so replicas exist both for redundancy and for search throughput. **Warm.** Indices that have rolled over and no longer take writes. They are still queried directly from local disk, so latency stays low, but the hardware can be denser and cheaper: more disk per node, less RAM per terabyte. Because the data is immutable, this is the natural place for a force merge (fewer segments, less per-segment overhead) and often a reduced replica count. **Cold.** Data queried occasionally — an investigation, a monthly report. The usual form is a **fully mounted searchable snapshot**: the index is snapshotted to a repository and then mounted from it, keeping a full local copy for query speed while the repository provides the durable second copy. Because the snapshot is the redundancy, replicas can be dropped, roughly halving the local storage cost compared with a normal replicated index. Searchable snapshots require a paid subscription tier. **Frozen.** Data that must be retained but is almost never read — compliance archives, year-old logs. Here the index is a **partially mounted searchable snapshot**: nothing but a bounded shared cache lives on local disk (sized by `xpack.searchable.snapshot.shared_cache.size`), and the blocks a query needs are pulled from object storage on demand and cached. The storage ratio is dramatic — a frozen node can serve far more data than it has disk — and the price is latency measured in seconds rather than milliseconds on a cold cache. ## How ILM moves an index between them An ILM policy has phases in a fixed order — hot, warm, cold, frozen, delete — and each phase has a `min_age` and a set of actions. ILM injects a `migrate` action into each phase automatically unless you have overridden allocation yourself with an `allocate` action; that injected action is what rewrites `_tier_preference` and causes shards to relocate. Two details about `min_age` matter. First, it is measured from the **rollover time** for an index that has rolled over, and from index creation otherwise — so `warm: min_age 7d` means seven days after that generation stopped taking writes, not seven days after the policy was written. Second, it is cumulative from that same origin rather than relative to the previous phase: warm at `7d` and cold at `30d` means the index reaches cold thirty days after rollover, not thirty-seven. Phases also constrain which actions are legal. `rollover` belongs to hot. `shrink`, `forcemerge` and `readonly` appear in hot (after rollover) and warm. `searchable_snapshot` is available in cold and is the *only* substantive action in frozen. `delete` and `wait_for_snapshot` belong to the delete phase. You cannot go backwards through the phases, and you cannot re-enter one. ## Choosing the shape The honest design question is where each transition earns its cost. Moving to warm costs a shard relocation and buys cheaper hardware; that is almost always worth it once writes stop. Moving to cold costs a snapshot and a mount and buys the removal of replicas. Moving to frozen buys an order of magnitude in retention per disk and costs query latency that must be acceptable to whoever queries it — if an on-call engineer needs sub-second answers over ninety days, ninety-day-old data does not belong in frozen. A cluster with no separate hardware still benefits from the policy: writing the phases now means that when warm nodes are added, the migration happens without touching a single index by hand. ## The tier that is not a tier `data_content` sits outside the hot-to-frozen progression. It holds indices with no time dimension, which is why a plain index created without a data stream defaults there. Confusing it with hot is common; the distinction is that content data is never expected to age out through phases at all.
- Is warm min_age 7d and cold min_age 30d thirty days after warm or after rollover?After rollover. Every phase's `min_age` is measured from the same origin — the rollover time for an index that rolled over, index creation otherwise — so the index reaches cold thirty days after it stopped taking writes, having spent twenty-three of them in warm. Reading the values as "time in the previous phase" is a common miscalculation that silently stretches retention.
- What happens to an index whose policy moves it to warm in a cluster with no warm nodes?Nothing bad. The tier preference is an ordered list, typically `data_warm,data_hot`, and allocation falls through to the first tier that actually has nodes — so the shards simply stay on hot nodes. The policy still records the index as being in the warm phase, and the shards relocate on their own when warm nodes are eventually added.
- Why can replicas be dropped for a fully mounted searchable snapshot in the cold tier?Because the snapshot in the repository is itself a durable second copy. A normal index needs a replica so a lost node does not lose data; a mounted searchable snapshot can simply be re-fetched from the repository onto another node. You still keep replicas if you need search throughput or fast failover, but the redundancy argument for them disappears.
saying these in an interview costs you the question
- Reads phase min_age as time spent in the previous phase
- Thinks frozen keeps a full local copy of the data
- Believes an index cannot allocate if its tier has no nodes
- Treats data_content as a synonym for the hot tier
- Expects writes to continue on an index after it moves to warm