Numbers at scale

The Elasticsearch essays · August 2026

Search asks "which documents match?" Analytics asks something else entirely: summarize a field across millions of documents. This essay is about the second question: the columnar layout that makes it cheap, the bucketing engine behind every dashboard, and the beautiful algorithm that trades a sliver of accuracy for almost all of the memory.

Search asks "which documents match?" Analytics asks something else entirely: summarize a field across millions of documents. The inverted index is the wrong tool; you'd be hopping all over the disk. This is what doc values are for, every field stored again as its own contiguous column:

5
Same question, avg(cpu). Run both reads, then drag the fields slider: as documents get wider, the document read's waste grows without bound, while the column read doesn't care how wide the documents are. Real log documents have hundreds of fields; imagine the slider at 400.

On columns, Elasticsearch builds aggregations: sort documents into buckets, by time, by term, by range, and compute metrics inside each. It's a histogram engine living inside the search engine, distributed like everything else. Here are 240 log events, bucketed live:

10m
Drag the interval: the same events regroup live. This is a date_histogram with a terms sub-aggregation, the query behind nearly every dashboard.

Some summaries, though, resist this treatment. "How many distinct users?" seems to require remembering every user you've seen, unbounded memory. Elasticsearch's cardinality aggregation refuses to pay that and uses HyperLogLog instead: hash every value and remember only the most surprising hash patterns seen, in a few fixed bytes. Feed it:

0
events seen
0
true distinct users
0
HyperLogLog estimate
error
exact set memory
sketch memory
256 bytes, forever
A real 256-register HyperLogLog running in your browser; the slider sweeps from 100 to 1,000,000 distinct users, logarithmically. Drag it slowly: the exact set's memory grows five thousand-fold; the sketch stays at 256 bytes and its error stays around the theoretical ±6.5%, no matter the scale. That indifference to scale is the whole trick.

This is a deliberate philosophy: at sufficient scale, a fast answer that is 99% right beats an exact answer you cannot afford. Percentiles get the same treatment. One kind of numeric data is so extreme, so relentless, that even columns weren't enough for it: metrics got their own engine.

One kind of numeric data is so extreme it outgrew even columns: metrics. That story has its own essay.