What Is Fielddata in Elasticsearch?
A friendly but thorough guide to the in-memory structure that lets Elasticsearch sort, aggregate and script on text, why it is switched off by default, how it can quietly exhaust your heap, and what to use instead.
Imagine a huge library with a wonderful index at the back of every book. Look up the word “volcano” and the index instantly tells you every page where it appears. That is perfect when you want to find pages. Now imagine someone asks a different question: “For page 214, list every word printed on it, in alphabetical order.” Your back-of-the-book index is suddenly the wrong tool, because it was built to go from words to pages, not from pages to words. To answer the new question quickly, you would have to flip the index upside down and keep the flipped copy on your desk.
Elasticsearch faces this exact situation every day, and the flipped copy on the desk is called fielddata. It is powerful, it is sometimes the only way to answer a certain kind of question, and it is also one of the most common reasons an Elasticsearch node runs out of memory. In this tutorial we start from zero: how Elasticsearch stores text, why sorting and aggregating need a different view of the data, what fielddata really is, how it is built, what it costs, how to watch it, and, most importantly, how to avoid needing it in the first place.
1The Big Picture: How Elasticsearch Stores and Finds Data
To understand fielddata you first need to understand the structure it is built from: the inverted index.
Documents, fields and indices
Elasticsearch stores information as documents, which are pieces of data such as a product, a blog post or a log line. Each document is made of fields, for example a title, a price and a date. A collection of similar documents is stored in an index, roughly comparable to a table in a traditional database. Elasticsearch splits each index into shards and spreads them over the nodes of a cluster, so that the work and the data are shared.
Inside each shard, the data is written into small immutable files called segments. A segment, once written, is never modified. New documents create new segments, and background merging combines small segments into larger ones. This detail will matter a great deal later, because fielddata is built one segment at a time.
The inverted index: a map from words to documents
When you store a text field such as “Quick brown fox,” Elasticsearch runs it through an analyzer, a small pipeline that breaks the text into tokens (the individual words), converts them to lowercase, and optionally removes noise words or reduces words to their roots. The result for our example might be the tokens quick, brown and fox. Elasticsearch then records, for each token, which documents contain it. This structure is the inverted index, and it is the reason full-text search is so fast.
Think of the index at the back of a school textbook. It lists words in alphabetical order and next to each word shows the page numbers where it appears. It is “inverted” because the book itself goes from pages to words, while the index goes from words to pages. If you want to know which pages mention “volcano,” the index answers in a moment.
graph LR
subgraph Docs["Documents"]
D1["Doc 1: quick brown fox"]
D2["Doc 2: brown bear"]
D3["Doc 3: quick red fox"]
end
subgraph Inv["Inverted index: term to documents"]
T1["brown: Doc 1, Doc 2"]
T2["fox: Doc 1, Doc 3"]
T3["quick: Doc 1, Doc 3"]
T4["bear: Doc 2"]
T5["red: Doc 3"]
end
D1 --> T1
D2 --> T1
D1 --> T2
D3 --> T2
D1 --> T3
D3 --> T3
D2 --> T4
D3 --> T5
The question the inverted index cannot answer well
The inverted index is brilliant for searching, but it is awkward for a whole different family of questions. Sorting results by a field, counting how many documents fall into each category, computing an average, or running a script that reads a field’s value for each matching document all need the opposite direction: given a document, what value does it have in this field? Going from a document to its terms with the inverted index would mean scanning the whole term dictionary for every single document, which is far too slow.
Search engines therefore keep a second, separate view of the data organised by document. Elasticsearch has two ways to provide that view. One is stored on disk and built when documents are indexed; it is called doc values. The other is built in memory on demand by flipping the inverted index upside down; that is fielddata.
Analyzer
The pipeline that turns raw text into tokens, usually by splitting, lowercasing and filtering.
Inverted index
A lookup from each token to the documents that contain it. Ideal for search.
Segment
A small, immutable chunk of a shard. Shards are made of many segments that merge over time.
Doc values
An on-disk, document-by-document view of field values, built at index time.
Fielddata
An in-memory, document-by-document view built at query time by uninverting the inverted index.
Heap
The memory area of the Java Virtual Machine where Elasticsearch keeps objects such as fielddata.
2So, What Exactly Is Fielddata?
Fielddata is a temporary, in-memory structure that maps each document to the terms it contains for a particular field.
A precise definition
Fielddata is a data structure that Elasticsearch builds in the heap memory of a node by reading the inverted index of a field and turning it around, so that for each document in a segment it can quickly answer “which terms does this document have in this field?” The process of flipping the structure is called uninverting. The finished result is stored in a cache on the node and reused for later requests that need the same field.
Three words in that definition deserve attention. It is in memory, which means it competes with everything else in the heap for space. It is built at query time, which means the first request that needs it pays a noticeable cost. And it is built from the inverted index, which means that for an analyzed text field it contains the individual tokens, not the original sentence.
Suppose the back-of-the-book index lists words with their pages, but a teacher now wants a table showing each page with all the words on it. A helpful student goes through the entire index, word by word, and writes each word onto the row of every page where it appears. The finished table is very quick to consult, but it took time to create, and it needs a whole extra desk to spread out. That table is fielddata, and the desk is your heap.
What operations need it?
Fielddata is used whenever Elasticsearch has to look at a field from the document’s point of view. The main cases are sorting results by a field, running aggregations such as terms counts or cardinality estimates, and reading field values inside scripts. For most field types this job is done by doc values instead, and fielddata is never involved. It matters mostly for one field type, the analyzed text field, which cannot use doc values at all.
Sorting
To order search results by a field, Elasticsearch must know each matching document’s value for that field. Doc values or fielddata provide that value quickly.
Aggregations
Counting documents per category, finding top terms, or computing statistics all need to walk over documents and read their values, which again requires the document-to-value view.
Scripting
When a script reads a field’s value for each document, for example to compute a score or a derived value, it reads from doc values or fielddata rather than from the original source text.
graph TD
Q["Request: sort, aggregate or script on a field"] --> C{"What type is the field?"}
C -->|"keyword, number, date, boolean, ip"| DV["Read doc values from disk, cached by the operating system"]
C -->|"text"| F{"Is fielddata enabled?"}
F -->|"No, the default"| ERR["Request fails with a clear error message"]
F -->|"Yes"| FD["Uninvert the inverted index into heap memory"]
Fielddata is not something you normally turn on or use every day. It is a fallback for one specific situation, sorting or aggregating on analyzed text. Most healthy clusters never need it at all.
3Why Text Fields Have Fielddata Turned Off
The default setting is a safety feature learned through many painful production incidents.
The default and the error message
On a text field, fielddata is disabled by default. If you try to sort, aggregate or script on such a field, Elasticsearch refuses and returns an error explaining that text fields are not optimised for operations that need per-document values. The message suggests using a keyword field instead, and mentions that you could enable fielddata on the field, but with a warning that this can use significant memory. That warning is not decoration; it reflects real experience.
This default was introduced with Elasticsearch 5.0, when the old single “string” field type was split into two distinct types, text for full-text search and keyword for exact values. Before that, string fields were analyzed by default and their fielddata could be loaded quietly on the first sort or aggregation. Many clusters ran out of memory without anyone understanding why. Splitting the types and switching fielddata off for text made the cost explicit and turned a hidden trap into a deliberate choice.
Think of a school cafeteria where the “eat as much as you like” button on the dessert machine used to be pressed by default. Everyone quickly got a stomach ache. The school removed the default and put up a sign: “You may press the button, but be warned.” Fielddata on text is now the same: allowed, but only if you press the button on purpose.
Why text fields are especially expensive
A keyword field stores one whole value per document, such as “Delhi” or “Blue.” A text field, by contrast, produces many tokens per document, and across millions of documents produces a very large dictionary of distinct terms. Uninverting it means creating structures that hold every term and connect each document to all of its terms. The more documents, the longer the text and the more varied the vocabulary, the bigger the structure becomes.
Moreover, this memory cost is paid on top of what the index already needs. The inverted index still sits on disk and in the file system cache. The fielddata copy is an extra, in-heap duplicate of the same information in a different shape. And because the heap is shared with everything else the node is doing, a single careless aggregation can push a node toward trouble.
Many people see the error message, find a forum answer that says “just enable fielddata,” and switch it on without measuring. It makes the error vanish, but it can also move the problem from a clear error message to a slow, mysterious memory crisis some weeks later.
4Fielddata Versus Doc Values
These two structures do the same job in very different ways, and the difference explains almost every practical decision.
Doc values: built early, stored on disk
Doc values are a column-oriented structure written to disk at index time, alongside the inverted index. For each field, the values are stored together, one after another, in document order. Reading the value for a document is therefore a quick, predictable lookup. Because the structure lives in files, the operating system’s file system cache keeps the hot parts in memory automatically, and the Java heap is not burdened with them. Doc values are enabled by default for almost every field type: keyword, numbers, dates, booleans, IP addresses, and more. The main exception is the analyzed text field.
Fielddata: built late, stored in memory
Fielddata takes the opposite approach. Nothing is prepared at index time. When a request first needs the structure, Elasticsearch reads the inverted index, builds the document-to-terms view, and keeps it in heap memory. The upside is flexibility, since it works on analyzed text without any extra index-time preparation. The downside is cost: a delay on first use, memory pressure, and extra pressure on garbage collection.
Doc values are like a class register that the teacher writes neatly, row by row, as each student arrives. It is stored in a filing cabinet and can be consulted at any time. Fielddata is like asking the teacher to reconstruct the register from scratch at the moment you need it, by listening to a recording of everyone announcing their names. It works, but it is slow to start and takes up the whole desk.
| Aspect | Doc values | Fielddata |
|---|---|---|
| When it is built | At index time, as documents are written | At query time, on first use of the field |
| Where it lives | On disk, cached by the operating system | In the Java heap |
| Default state | On for most field types | Off for text fields |
| Works on analyzed text | No | Yes, when enabled |
| First-request latency | Low | High, because of uninverting |
| Memory pressure on heap | Low | High |
| Disk cost | Extra disk space per field | None extra, uses the existing inverted index |
| Best for | Exact values, numbers, dates, categories | Rare cases needing token-level aggregation on text |
graph LR
subgraph Index["At index time"]
W["Document is written"] --> INV["Inverted index on disk"]
W --> DVS["Doc values on disk (keyword, numbers, dates)"]
end
subgraph Query["At query time"]
DVS --> OSC["Operating system file cache"]
INV -->|"only if fielddata is enabled"| UNINV["Uninvert into heap"]
UNINV --> HEAP["Fielddata cache in JVM heap"]
end
If a field is used for sorting or aggregations, make it a type that has doc values, such as keyword. Reach for fielddata only when you truly must aggregate on the analyzed tokens of a text field, and even then, think twice.
5Text, Keyword and the Multi-Field Solution
The cleanest way to avoid fielddata is to store the same value in two shapes, one for searching and one for sorting.
Two field types for two jobs
A text field is analyzed, broken into tokens, and designed for full-text search: you can find a document by searching for a single word in a long paragraph. A keyword field is stored as one exact value, not analyzed, and is designed for filtering, sorting and aggregating. If a product name is “Red Running Shoes,” a text field lets people find it by typing “running,” while a keyword field treats the whole phrase as one unit that can be counted or alphabetised.
Text field
Analyzed into tokens. Great for search relevance. No doc values, so sorting and aggregations need fielddata.
Keyword field
Stored as one exact value. Has doc values by default, so sorting and aggregations are efficient.
Multi-field
One source value indexed in several ways, such as a text version for search and a keyword version for sorting.
Normalizer
A light-weight analyzer for keyword fields that can lowercase or clean a value while keeping it as one token.
Multi-fields: the everyday answer
A multi-field lets you index one value in more than one way. The typical pattern is a main field of type text, plus a sub-field of type keyword. You search on the main field and you sort or aggregate on the sub-field. When you let Elasticsearch create mappings dynamically for string values, it does this for you by default: a text field with a keyword sub-field, where the keyword version ignores values longer than a set number of characters, 256 by default. That is why many users see fields called something like name and name.keyword.
The sub-field costs some disk space, because the doc values are written to disk, but it costs almost nothing on the heap. That trade is nearly always worth it. You pay a little at index time and a little in storage, and you avoid the runtime memory hazards of fielddata.
A library keeps every book both on the shelf by topic, so you can browse ideas, and in a neat catalogue sorted by title, so you can look up an exact name. Keeping both costs a little extra effort when a book arrives, but saves enormous effort every time someone asks a question. The keyword sub-field is the sorted catalogue.
What about case-insensitive sorting?
A plain keyword field is case-sensitive, so “apple” and “Apple” sort in different places and count as different values. If you want them treated as one, you can attach a normalizer that lowercases the value before it is stored. The value remains a single token, so it still has doc values and needs no fielddata. This is far more predictable than sorting on analyzed tokens, which would split “New York” into two separate words.
Keyword values above the configured length limit are simply not indexed in that sub-field. If your field can hold long paragraphs, do not expect to aggregate on them. Long free text is meant for searching, not for grouping.
6How Fielddata Is Loaded and Kept
Understanding the lifecycle explains why the first request is slow and why memory can creep upward.
Lazy loading
By default, fielddata is loaded lazily. Nothing happens when a text field with fielddata enabled is first indexed. The first time a sort, aggregation or script needs it, each shard reads the relevant terms from the inverted index of each segment and builds the structure. That work uses processor time and disk reads, and the memory needed is reserved in the heap. The request that triggers it can be far slower than later ones.
A request arrives
A user runs an aggregation on a text field that has fielddata enabled. The shard checks the fielddata cache for that field in each segment.
The circuit breaker is consulted
Before loading, Elasticsearch estimates how much memory the structure will need and checks it against a safety limit. If it would exceed the limit, the request fails cleanly instead of risking the node.
The inverted index is uninverted
For every segment, terms are read one by one and the documents containing them are recorded, building a document-to-terms structure.
The result is cached
The finished structure is stored in the fielddata cache in the heap, tied to the segment it came from.
Later requests are fast
Subsequent requests find the structure in memory and read from it immediately, until the segment disappears or the cache is cleared or trimmed.
Segments make it a moving target
Because segments are immutable and new ones appear continuously as you index, fielddata is tracked per segment. When new documents arrive and a refresh creates a new segment, the next request must load fielddata for that new segment, while the older segments’ entries are still valid. When segments are merged, the old segments are retired and their fielddata is released, and the merged segment needs a fresh load the next time it is used. On a cluster with heavy indexing, this creates a steady background rhythm of loading and freeing.
sequenceDiagram
participant U as User
participant S as Shard
participant B as Circuit breaker
participant H as Fielddata cache in heap
U->>S: Aggregate on text field
S->>H: Is fielddata loaded for each segment?
H-->>S: No
S->>B: Estimate memory needed
B-->>S: Within limit
S->>S: Uninvert inverted index
S->>H: Store structure
S-->>U: Aggregation result (slow first time)
U->>S: Same aggregation again
S->>H: Loaded already
S-->>U: Aggregation result (fast)
Eager versus lazy
Loading on demand means users can feel the cost. Some setups prefer to pay the cost in advance, so that no user request has to wait. Elasticsearch offers a setting to build structures eagerly, when new segments become visible after a refresh, rather than waiting for the first query. Eager loading moves the cost from user requests to the refresh step. It gives smoother query latency but slows down refreshes and uses memory whether or not anyone runs the query. It suits fields that are certain to be used frequently, and it is a poor choice for fields that are rarely queried.
Lazy loading is friendly to memory but unfriendly to the first user. Eager loading is friendly to users but unfriendly to indexing speed and memory. Neither is free; choose based on how predictable your queries are.
7Inside the Machine: How Uninverting Really Works
A closer look at the loading step shows exactly why the cost grows with your data.
Step one: the term dictionary
Every segment stores, for each indexed field, a sorted list of all the distinct terms found in that field, called the term dictionary. Next to each term, the segment stores a postings list, which is simply the list of document numbers in that segment that contain the term. The term dictionary and postings lists together are the inverted index. When fielddata is built, Elasticsearch walks through this dictionary from the first term to the last, one term at a time.
Step two: filling in the document rows
For each term, the loader reads its postings list and, for every document in the list, records that this document has this term. By the end of the walk, each document has a small list of the terms it contains, the exact opposite view of the one stored on disk. Terms are kept as compact numbers pointing into a shared dictionary of the actual text, so the same word is not stored again and again for every document that has it.
Picture a teacher holding the back-of-the-book index and a blank grid with one row for each page. The teacher reads the index from A to Z. For the word “apple,” which appears on pages 3, 9 and 40, the teacher writes “apple” into the rows for pages 3, 9 and 40. After the last word, every row lists the words on that page. Longer indexes and more pages mean more writing and a bigger grid.
What decides how big the result is?
Number of documents
Every document in the segment needs a row, even if the row is short. More documents mean a bigger structure.
Number of distinct terms
Every unique word must be stored once in the shared dictionary. Rich vocabularies with many rare words cost the most.
Terms per document
A long paragraph contributes many tokens to its row, while a short title contributes only a few.
Number of segments
Each segment builds its own structure, so many small segments add overhead compared with a few large ones.
Analyzer choice
Analyzers that create extra tokens, such as word-fragment analyzers for autocomplete, multiply the term count dramatically.
Frequency filter
Filtering out very rare and very common terms can shrink the structure to a fraction of its natural size.
flowchart LR
A["Term dictionary of a segment"] --> B["Read next term"]
B --> C["Read postings list for that term"]
C --> D["For each document in the list, add the term to its row"]
D --> E{"More terms?"}
E -->|"Yes"| B
E -->|"No"| F["Document-to-terms structure complete and cached"]
Why this work cannot be skipped
Some people ask whether Elasticsearch could load only the parts needed for a particular query. In practice, an aggregation or sort usually touches a large share of the matching documents, and those documents are spread across the whole segment. Loading only a slice would mean repeating the expensive term walk many times. Doing it once for the whole segment and caching the result is the sensible engineering choice, which is why the cost is front-loaded and heavy.
Fields analyzed into word fragments, such as edge-based tokens used for type-ahead suggestions, produce a huge number of tiny tokens per word. Enabling fielddata on such a field can be many times more expensive than on a normal text field, and its buckets are meaningless fragments. Never enable it there.
8Global Ordinals: The Hidden Cousin of Fielddata
Even if you never enable fielddata on a text field, a related in-memory structure may appear when you aggregate on keyword fields.
What is an ordinal?
Comparing long strings again and again is slow. To speed up counting, Elasticsearch gives every distinct term in a segment a small whole number, an ordinal, based on its alphabetical position. The aggregation then works with these small numbers, which are cheap to compare and count, and converts them back to text only at the end when building the result.
Imagine a class of thirty students who are always called by their roll numbers instead of their full names when the teacher counts hands. Counting is quicker with “roll number 7” than with a long name. Only when announcing the winner does the teacher look up the name that goes with the number.
Why “global”?
Ordinals in one segment do not match ordinals in another, because each segment has its own list of terms. To combine results across the segments of a shard, Elasticsearch builds a global ordinals structure that gives every distinct term one number valid across all segments of the shard. Building it needs to read through the terms of all segments, so it can be expensive for fields with a large number of distinct values, and it must be rebuilt when the set of segments changes.
Global ordinals are stored in the heap and count toward the same memory accounting and circuit breaker as fielddata. That is why an aggregation on a high-cardinality keyword field, one with millions of different values, can show up in your fielddata memory statistics even though you never enabled fielddata on it.
Segment ordinal
A small number for each term within one segment, based on sorted order.
Global ordinal
A shard-wide numbering of terms that lets aggregations combine segments quickly.
Eager global ordinals
A setting that builds the structure at refresh time instead of at the first aggregation.
Cardinality
The number of distinct values in a field. High cardinality means bigger ordinals structures.
Fields with unique or nearly unique values, such as identifiers, session tokens or full URLs, make expensive aggregation targets. If you truly need to count them, consider approximate counting or a different modelling approach rather than grouping by each individual value.
9Enabling Fielddata on Text: When and How to Think About It
Sometimes you really do need to aggregate on analyzed tokens. Here is what that means and what to watch for.
What you actually get
When fielddata is enabled on a text field, sorting and aggregating work on the analyzed tokens, not on the original sentence. If a document’s field contains “New York City,” an aggregation on that field will produce separate buckets for new, york and city, all lowercase, and probably not what most people expect when they think of counting cities. Analysis steps such as stemming, if configured, would also change the words that appear in the results.
There are legitimate uses. If you want to find the most common words in a body of text, for example the most frequent words in customer reviews, aggregating over analyzed tokens is exactly the point. But for names, categories, statuses and identifiers, tokens are the wrong unit, and a keyword field is the correct tool.
A good reason
A research team wants to explore the most common tokens across a small, bounded set of free-text survey answers, on a dedicated index where memory has been sized for it.
A poor reason
A developer saw the error message when sorting by product name, enabled fielddata on a text field with millions of documents, and moved on. Sorting by tokens gives odd results and the memory cost grows with the index.
A better answer to the poor reason
Add a keyword sub-field, ideally with a lowercase normalizer, and sort on that. It is faster, uses doc values, and sorts on the whole product name as people expect.
Controlling the size with a frequency filter
Elasticsearch lets you limit which terms are loaded into fielddata using a frequency filter. You can tell it to load only terms that appear in a certain range of documents, either as absolute counts or as fractions of the segment, and to skip small segments altogether. Very rare terms, such as typos and one-off tokens, and extremely common terms, such as filler words, are often useless for analysis yet take up a lot of memory. Filtering them out can shrink fielddata dramatically. The trade-off is that the filtered terms will not appear in your results.
When making a table of every word in the school library, you might decide to skip words that appear only once in the whole library, which are mostly typos, and also skip “the” and “and,” which appear everywhere. The table becomes much smaller and still tells you what you wanted to know.
Changing the setting on an existing field
The fielddata option on a text field is one of the few mapping properties that can be changed on an existing field, because it does not affect how data is indexed, only what happens at query time. That makes it easy to turn on, and also easy to turn on carelessly. Turning it back off does not immediately free memory already used; the cached structures stay until they are evicted or cleared.
Before enabling fielddata, ask three questions. Can a keyword sub-field do this job? Can a specialised aggregation for text, such as one designed to find unusual terms in text, do it without fielddata? Can the value be computed at query time from the stored source using a runtime field? Only if all three answers are no should fielddata be considered.
10The Memory Problem: Heap, Garbage Collection and Instability
Fielddata is dangerous not because it is slow, but because it takes memory that every other part of the node also needs.
Why heap memory is precious
Elasticsearch runs on the Java Virtual Machine, which manages memory in a fixed-size area called the heap. Everything the node keeps as live objects, including caches, request buffers, the cluster state and fielddata, lives there. A well-run node keeps its heap a comfortable distance from full, because the JVM periodically runs garbage collection to reclaim unused memory. When the heap is nearly full, garbage collection runs more often and for longer, and the node can appear frozen while it is busy cleaning up.
Good practice is to set the heap to no more than about half of the machine’s memory, and below the size at which the JVM loses its compact-pointer optimisation, generally around thirty gigabytes. The rest of the memory is intentionally left to the operating system, which uses it as a file system cache. This is exactly the memory that makes doc values fast. So the two structures compete in opposite ways: doc values lean on the operating system’s cache, while fielddata eats the very heap that has been carefully limited.
Imagine a classroom desk with limited space. Your books, notebook, pencil case and lunch all have to fit on it. Fielddata is like unrolling a giant poster across the desk: everything else has to squeeze into the corner. When the desk is full, you spend all your time shuffling things around instead of working.
The chain reaction
Fielddata grows
Several large fields are loaded across many segments, and the fielddata cache fills a large slice of the heap.
Free heap shrinks
Other work, such as searches, indexing buffers and aggregation results, has less room and forces more frequent garbage collection.
Pauses get longer
Garbage-collection pauses stretch from milliseconds to seconds. Requests to the node slow to a crawl.
Health checks fail
If a pause is long enough, other nodes conclude the node is gone. It may be removed from the cluster, forcing shards to move and adding more load to the remaining nodes.
Cascade
The extra work on the survivors causes them to load more fielddata or run out of memory too, and the problem spreads across the cluster.
Why memory pressure hurts the whole cluster
This chain reaction shows why a single misjudged aggregation is not only that user’s problem. A node that is struggling with memory can be evicted from the cluster, and if it is also serving as the elected master, the cluster must run a new election. That is why teams often separate the master role from busy data nodes. Fielddata-heavy workloads belong on data nodes with generous heap headroom, never on the nodes that coordinate the cluster.
11Guard Rails: The Fielddata Circuit Breaker and Cache Size
Elasticsearch includes automatic protections that stop runaway memory use before a node falls over.
What is a circuit breaker?
In an electrical system, a circuit breaker trips when too much current flows, cutting the power to prevent a fire. In Elasticsearch, a circuit breaker estimates how much memory an operation will need, and if that would push usage above a limit, it rejects the operation with an error instead of allowing an out-of-memory failure. The rejected request fails, but the node stays healthy and continues serving everyone else.
A lift has a weight limit. When too many people step in, an alarm sounds and the doors refuse to close. It is annoying for the person who has to wait, but far better than the cable snapping.
The relevant breakers
The fielddata circuit breaker estimates the memory needed to load fielddata and rejects the request if loading would exceed its limit, which by default is a large fraction of the heap, around forty percent. It also applies a small overhead multiplier to estimates to stay on the safe side. Above it sits the parent circuit breaker, which watches total memory use across all the breakers and, in modern versions, can look at real heap usage; its default limit is much higher, around ninety-five percent of the heap. There are further breakers for request memory and in-flight data, but the fielddata breaker is the one that trips when fielddata loading is too greedy.
When a breaker trips, the error message says the data was too large, and it reports the estimated size and the limit. Seeing this message is a clear sign that a request is asking for more memory than the node can safely provide. The right response is to change the query or the mapping, not simply to raise the limit.
| Guard rail | What it does | Default behaviour |
|---|---|---|
| Fielddata circuit breaker | Rejects a fielddata load that would exceed the limit | Limit around 40 percent of heap |
| Parent circuit breaker | Caps total memory across all breakers | Limit around 95 percent of heap in modern versions |
| Fielddata cache size | Optionally evicts old entries when the cache reaches a set size | Unbounded unless configured |
| Frequency filter | Loads only terms in a chosen frequency range | Off unless configured on the field |
The cache size setting
By default the fielddata cache has no size limit; entries stay until their segment goes away or someone clears the cache. You can set a maximum size, in which case the least recently used entries are evicted when the cache is full. This may sound like a cure, but it hides a subtle trap. If the limit is smaller than the fielddata that queries actually need, entries are evicted and then reloaded again and again, an expensive cycle sometimes called thrashing. It is also important that any cache size be lower than the circuit breaker limit, or the breaker will trip before eviction can help.
Problem
Raising the fielddata circuit breaker limit to make a “data too large” error go away.
Why It’s Harmful
The breaker exists to protect the node. Raising it removes the protection while the underlying demand stays the same, pushing the node closer to heap exhaustion and long garbage-collection pauses.
Correct Approach
Reduce the demand: aggregate on a keyword field, add a frequency filter, narrow the query, or add nodes and heap sized for the workload.
12Estimating and Planning Fielddata Memory
Guessing is dangerous. A little measuring and a little multiplication go a long way.
There is no magic formula
The memory needed by fielddata depends on the vocabulary, the number of documents, the analyzer, the number of segments and the frequency filter. Because these factors interact, no simple formula gives a precise answer. The reliable method is empirical: load fielddata for the field in a realistic test environment with realistic data and read the memory figure from the statistics. Then scale that figure thoughtfully to production volumes.
Build a representative sample
Copy a realistic slice of production data, such as a few million documents with real vocabulary, into a test index that uses the same mapping and analyzers.
Trigger the load deliberately
Run the sort or aggregation you plan to support and read the fielddata memory from the cat or node statistics for that field.
Scale with care
Estimate how memory grows with data. Memory usually grows with the number of documents and, less predictably, with vocabulary. Add a generous margin, since real data is often messier than samples.
Multiply by copies
Every shard copy, primary or replica, that serves the request builds its own structure on its own node. Replicas therefore multiply total cluster memory use, though each node holds only its own share.
Compare with headroom
Check the per-node figure against the breaker limit and against the free heap left after everything else the node does. Leave room for peaks, not just averages.
Where the memory lands
Fielddata is held on the nodes that hold the shards, not on the node that received the request. If a field’s data is concentrated in a few large shards, the nodes holding them carry more of the load. If shards are spread evenly, the load is spread too. Uneven shard sizes are a common cause of one node hitting its breaker while its neighbours are calm.
| Planning question | Why it matters | What to check |
|---|---|---|
| How many documents will the field cover? | Each document needs a row in every segment | Index size projections over the retention period |
| How rich is the vocabulary? | Distinct terms drive dictionary size | Terms count on a sample of real data |
| How many shard copies serve the queries? | Each copy loads independently | Shard and replica counts per node |
| How much heap is free at peak? | Fielddata competes with everything else | Heap percentage during busiest hours |
| How often do segments change? | New segments trigger new loads | Indexing rate, refresh interval, merge activity |
| Can a frequency filter be applied? | May shrink memory dramatically | Whether rare or common terms are useful |
Before hiring a coach for a school trip, you count the students, count the teachers, and add the luggage. If you only guess “about thirty,” you may find on the day that fifty people turn up. Measuring a sample first is the difference between a smooth trip and a bus that cannot close its doors.
If your estimate says fielddata would consume more than a modest slice of the fielddata breaker limit on a node, treat that as a sign to redesign, not to buy bigger machines. A keyword sub-field almost always costs less than the hardware needed to hold the equivalent fielddata.
13Fielddata, Other Caches and Query Performance
Elasticsearch has several caches, and mixing them up is a very common source of confusion.
A tour of the caches
People often use the word “cache” for any memory-based speed-up, but Elasticsearch has distinct caches with different purposes, different owners and different lifetimes. Understanding which is which helps you avoid clearing the wrong one or blaming the wrong one for a slow query.
| Cache | What it stores | Where it lives | Typical use |
|---|---|---|---|
| Fielddata cache | Document-to-terms structures and global ordinals | JVM heap | Sorting, aggregations and scripts on fields |
| Node query cache | Results of frequently used filters | JVM heap, limited to a share of the heap | Speeding up repeated filter clauses |
| Shard request cache | Whole results of certain searches, mostly aggregations without hits | JVM heap | Dashboards repeating the same request |
| File system cache | Raw index files, including doc values | Operating system memory outside the heap | Making disk reads fast for everything |
graph TD
subgraph HeapArea["JVM heap: limited and precious"]
FD["Fielddata cache"]
QC["Node query cache"]
RC["Shard request cache"]
OT["Request buffers, cluster state, indexing buffers"]
end
subgraph OSArea["Operating system memory: outside the heap"]
FS["File system cache: inverted index files and doc values"]
end
Why the difference matters for tuning
Clearing the fielddata cache does not clear the request cache, and clearing the request cache does not free fielddata. If a dashboard is slow, the cause may be a cold fielddata load, a cold file system cache after a restart, or simply a heavy query. Diagnosing correctly saves hours. A cold restart, for example, empties every cache at once, so the first queries after startup are slow for several reasons together, not only because of fielddata.
The refresh interval and eager loading
Elasticsearch makes new documents searchable by refreshing, which by default happens about once a second on active indices. Each refresh may create a new segment, and new segments need fresh structures if a query uses them. If you have chosen eager loading for global ordinals, each refresh triggers that build work. On an index receiving constant writes, that can become a heavy tax. A common compromise is to lengthen the refresh interval for indices that do not need near-real-time visibility, which reduces the number of new segments and the associated rebuild work.
Merging and read-only indices
Because fielddata and ordinals are built per segment, having fewer, larger segments reduces overhead. For indices that are no longer written to, such as yesterday’s logs, merging down to fewer segments can make later aggregations cheaper and more predictable. Combined with moving such indices to nodes with suitable resources, this is a standard pattern for time-based data.
Hot indices that receive writes need fast refreshes and flexible memory. Older, read-only indices can be consolidated and given lighter, cheaper resources. Fielddata and ordinals for old, stable segments stay valid for as long as those segments exist, so stable data is friendlier to caches than churning data.
Symptom: slow only after a restart
Likely a mix of cold caches. The file system cache, and any fielddata or ordinals, must be rebuilt. Consider eager loading only for the most important keyword fields, and warm critical dashboards gently after restarts.
Symptom: slow at the top of every hour
Perhaps a scheduled dashboard refreshes at the same instant, causing simultaneous loads. Stagger schedules, or pre-aggregate the results it needs.
Symptom: fast for days, then suddenly slow
Possibly a merge or a batch of new segments invalidated structures on a large index, or a new query pattern started using an unloaded field.
14Monitoring Fielddata in a Live Cluster
You cannot manage what you cannot see, and Elasticsearch offers several simple views into fielddata usage.
Where to look
The cat API for fielddata shows, for each node, how much memory each field’s fielddata is using. The node statistics API reports fielddata memory in bytes and the number of evictions, both per node and optionally per field. The index statistics API gives the same picture per index. The breaker statistics section of node stats reports each breaker’s limit, its estimated current usage, and how many times it has tripped. Together these tell you which fields are large, which nodes are affected, and whether protections are being triggered.
Cat fielddata
A compact table of memory used by each field on each node. The quickest first look.
Node stats for indices
Fielddata memory size and evictions per node, with optional per-field detail.
Index stats
Fielddata usage grouped by index, useful for finding which index is responsible.
Breaker stats
Limits, current estimates and trip counts for each circuit breaker on each node.
Heap and GC metrics
Heap percentage in use and garbage-collection pause times, the ultimate symptoms.
Slow logs and query logs
Reveal which slow queries triggered heavy loading, so you can trace cause to a specific application.
What healthy looks like
On a well-designed cluster that uses keyword fields and doc values for sorting and aggregations, fielddata memory is small or close to zero for text fields, and modest for global ordinals. Evictions are rare or absent. Breaker trip counts stay at zero. Heap usage follows a steady sawtooth pattern, rising as memory is used and falling as garbage collection reclaims it, without creeping upward over days.
flowchart TD
A["Alert: heap high or breaker tripped"] --> B["Check fielddata memory by field"]
B --> C{"Is one field dominant?"}
C -->|"Yes"| D["Find queries using that field"]
C -->|"No"| E["Check other heap users: request buffers, shard count"]
D --> F{"Is it text with fielddata enabled?"}
F -->|"Yes"| G["Move to keyword sub-field or add frequency filter"]
F -->|"No, keyword"| H["Check cardinality and global ordinals"]
Set alerts on heap percentage, long garbage-collection pauses, breaker trips and fielddata evictions. A trip count that rises from zero is the earliest and clearest signal that something new is asking for too much memory.
15Fixing Fielddata Problems: A Practical Playbook
When memory trouble strikes, work from the gentlest fix to the most drastic one.
Identify the offender
Use the fielddata views to find which field and which index take the most memory, and which queries touch them.
Redirect the query to a keyword field
If the field has a keyword sub-field, change the application to sort or aggregate on it. This usually removes the need for fielddata entirely.
Add a keyword sub-field if none exists
Update the mapping to add the sub-field, then rebuild the data so existing documents populate it. This typically means reindexing into a new index, or running an update-by-query on the same index.
Turn fielddata off and clear the cache
Once no query depends on it, disable fielddata on the text field and clear the fielddata cache for the affected indices so memory is released at once rather than waiting for eviction.
Tune if fielddata is truly required
Apply a frequency filter, restrict the query to smaller time ranges or fewer indices, and give the relevant data nodes enough heap and headroom.
Prevent recurrence
Update index templates so new indices are created with the correct multi-field mapping, and add checks to catch fielddata being enabled by accident.
The cache-clearing step in context
Clearing the fielddata cache is a quick, targeted tool: you can clear it for one index, several indices, or specific fields. It is a good emergency measure and a good cleanup step after a mapping change. But clearing only frees memory now. If queries continue to ask for the same fielddata, the cache will simply refill. Treat cache clearing as a bandage, and treat the mapping or query change as the cure.
Why reindexing is sometimes unavoidable
Adding a new sub-field to an existing mapping affects only documents indexed after the change. Older documents will not have values in the new sub-field until they are re-processed. Reindexing to a new index with the improved mapping, then switching an alias over to it, is the cleanest approach because the switch can be almost instant for users, and the old index remains available for rollback until you are confident.
Problem
Enabling fielddata on a text field across all indices, through a broad template, so that any application can sort or aggregate on it.
Why It’s Harmful
It turns a hidden memory cost into a system-wide risk. Any user with access to run a query can trigger large loads, and the cost grows with every new index.
Correct Approach
Model the data properly with keyword sub-fields, keep fielddata off by default, and enable it narrowly, on specific fields and indices, only after review.
16A Worked Example: From Error Message to Healthy Cluster
Let us follow a realistic story from the first error to the final fix.
The scenario
A team runs a support-ticket search application. Each ticket has a title, a long description, a customer company name, a status and a creation date. The application shows a table of tickets that users can sort by company name, and a chart of the ten most common companies. The team maps every string as a text field, because it seemed the natural choice, and relies on dynamic mapping for the rest.
Act one: the error
A developer adds the “sort by company name” feature. The first test fails with the message saying that text fields are not optimised for sorting and that fielddata could be enabled. A colleague suggests enabling fielddata on the company field, because it “just works.” The developer applies the change to the live mapping, and the feature suddenly works. Everyone is happy, and the change is shipped.
Act two: the slow burn
Over the following weeks, ticket volume grows. The company field contains names such as “Acme Trading Private Limited,” which the analyzer splits into several lowercase tokens. The chart of top companies now shows entries such as “private,” “limited” and “trading” as the biggest “companies,” which confuses the business team. At the same time, heap usage on the data nodes creeps higher, and the monitoring dashboard shows garbage-collection pauses stretching to several seconds during busy hours.
sequenceDiagram
participant Dev as Developer
participant ES as Elasticsearch
participant Ops as Operations
Dev->>ES: Sort by company (text field)
ES-->>Dev: Error: fielddata disabled on text
Dev->>ES: Enable fielddata on company
ES-->>Dev: Sort works
Note over ES: Weeks pass, data grows, heap fills
Ops->>ES: Alerts: long GC pauses
ES-->>Ops: Breaker trips on some aggregations
Ops->>ES: Investigate fielddata memory by field
ES-->>Ops: Company field is the largest consumer
Act three: the diagnosis
The operations engineer opens the cat fielddata view and sees that the company field dominates the fielddata memory on every data node. Node statistics show growing memory and the breaker statistics show trips. The engineer cross-checks the slow log and confirms that the sort and the top-companies chart are the queries causing the loads. The weird buckets in the chart make the modelling error obvious: the field is being aggregated as tokens rather than as whole company names.
Act four: the fix
Design the new mapping
Company becomes a keyword field with a lowercase normalizer for sorting and grouping, plus, if free-text search on company is required, a text sub-field for searching.
Create a new index and reindex
A new index is created with the corrected mapping and all tickets are copied into it, while the old index continues to serve live traffic.
Update the application queries
The sort and the chart now target the keyword field. The team tests both on the new index and compares results with expectations, especially the top-company chart.
Switch the alias
The application reads through an alias. The alias is moved from the old index to the new one in a single step, so users notice nothing except a faster, more accurate chart.
Clean up and confirm
After a safe waiting period, the old index is deleted, which frees its fielddata. The team confirms that fielddata memory has dropped to near zero and that pauses have disappeared.
The original error message was trying to help. It pointed at the right fix, a keyword field, and warned about the wrong one. Reading it carefully at the beginning would have saved weeks of trouble.
17A Safe Migration Checklist: From Fielddata to Keyword Fields
Changing how a field is modelled touches data, queries and people, so a checklist keeps it calm.
Before you start
List every consumer
Find every application, dashboard, saved search and script that sorts, aggregates or scripts on the field.
Decide the new shape
Choose keyword, text, or both, and decide about normalizers and length limits for each field involved.
Estimate space and time
Reindexing needs enough disk for a second copy and enough time to finish without hurting live traffic.
Confirm backups
Take a recent snapshot so that a rollback is always possible if something unexpected appears.
The migration path
Update the template
Change the index template first, so that any new index, such as the next rollover, is created with the correct mapping automatically.
Create the target index
Create a fresh index with the corrected mapping. It is empty and unused by applications until the switch.
Copy the data
Use the reindex feature to copy documents in batches, throttling if necessary so that live search is not slowed.
Verify counts and samples
Compare document counts between old and new indices, and compare results of key queries on both, including sorted lists and grouped counts.
Catch up on late writes
If the source index is still receiving writes, run a final incremental copy or pause writes briefly, so the new index is fully current.
Switch the alias
Move the alias to the new index in one atomic operation, so applications see a clean cut-over.
Observe and retire
Watch heap, breaker and latency metrics for a period. When confident, remove fielddata settings and delete the old index.
flowchart LR
APP["Application uses alias"] --> ALIAS["Alias: tickets"]
ALIAS -->|"before switch"| OLD["Old index: text with fielddata"]
ALIAS -.->|"after atomic switch"| NEW["New index: keyword sub-fields"]
OLD -->|"reindex copies data"| NEW
Problem
Applications that hard-code concrete index names, forcing every mapping change to become an application release.
Why It’s Harmful
A migration that could be a quiet alias switch turns into a coordinated deployment, and teams are tempted to keep a bad mapping simply to avoid the effort.
Correct Approach
Always read and write through aliases, so that the physical index behind the name can change freely.
18Troubleshooting Cheat Sheet: Symptoms, Causes and Cures
When something looks wrong, match the symptom to the most likely cause, then apply the gentlest fix.
| Symptom | Likely cause | First fix to try |
|---|---|---|
| Error about text fields not being optimised for sorting or aggregations | Sorting or aggregating on an analyzed text field without fielddata | Use a keyword sub-field instead |
| Error saying data is too large, mentioning the fielddata breaker | A fielddata or ordinals load would exceed the limit | Change the query or field, not the limit |
| Buckets are single lowercase words | Aggregating tokens from a text field | Aggregate on the keyword version |
| Heap climbs steadily over days | Fielddata or ordinals accumulating with data growth | Check fielddata memory by field and remodel |
| Long garbage-collection pauses | Heap nearly full, often from caches | Reduce fielddata, clear caches, check shard counts |
| Nodes dropping out of the cluster under load | Pauses long enough to fail health checks | Reduce memory demand, separate roles |
| High fielddata evictions | Cache size limit smaller than working set | Remove need for fielddata, or resize deliberately |
| Aggregation on a keyword field is slow the first time only | Global ordinals built at first use | Consider eager global ordinals for that field |
| Sorting seems to ignore capital letters oddly | Case-sensitive keyword ordering | Add a lowercase normalizer |
| Aggregation returns nothing for long values | Values exceed the keyword length limit | Aggregate on a shorter derived field |
A calm mental checklist
When faced with a memory alarm, resist the urge to change settings at random. First identify what is using memory, using the fielddata views. Second, identify which queries cause it, using logs. Third, decide whether the queries or the mapping should change. Fourth, apply the change in a test environment and measure. Only then apply it to production. Most incidents resolve at step three, when someone realises a field is modelled for the wrong job.
Raising heap to the maximum, disabling breakers, or restarting nodes repeatedly can make things worse or merely hide the problem. A restart clears memory but not the cause, and the same queries will simply refill it.
Problem
Scheduling a periodic job that clears all caches to keep memory “under control.”
Why It’s Harmful
Every clear forces the next queries to rebuild everything, causing recurring latency spikes. It treats a symptom, and it also throws away caches that were working well.
Correct Approach
Find and fix the field or query responsible for excess memory. Clear caches only as a targeted, one-off step after a mapping change.
19Design Patterns That Avoid Fielddata
The best fielddata strategy is a data model that never needs it.
Search with text, analyse with keyword
Give every descriptive string a text field for searching and a keyword sub-field for sorting and grouping. Decide which fields truly need each capability, and skip the unneeded one to save disk.
Normalised keyword fields
Attach a lowercase normalizer to keyword fields where case should not matter, such as tags and user-entered categories. Grouping and sorting then behave the way people expect.
Dedicated fields for exact identifiers
Store codes, statuses and identifiers as keyword only, not as text at all. There is no benefit to analysing a product code, and keyword fields carry doc values automatically.
Numeric and date fields for numbers and dates
Never store numbers or dates as text. Proper numeric and date types use doc values, support range queries and are compact.
Specialised aggregations for text exploration
When you want to find interesting or unusual words in a body of text, use an aggregation designed for that purpose, which analyses text without requiring fielddata on the field.
Runtime fields for occasional needs
When you need a derived value only now and then, a runtime field computes it at query time from stored source, avoiding index-time cost. It is slower per query than an indexed field, but it does not permanently consume heap or disk.
Eager global ordinals for hot keyword fields
For a keyword field that is aggregated on constantly in a read-heavy index, building global ordinals at refresh time removes the delay for the first user request. Use it selectively.
flowchart TD
S["Need to sort or aggregate on a string"] --> Q1{"Is the value a whole label such as a name, tag or status?"}
Q1 -->|"Yes"| K["Use a keyword field or keyword sub-field with doc values"]
Q1 -->|"No, it is long free text"| Q2{"Need the most frequent or unusual words?"}
Q2 -->|"Yes"| SA["Use a text-aware aggregation, no fielddata needed"]
Q2 -->|"No"| Q3{"Need a derived value occasionally?"}
Q3 -->|"Yes"| RF["Use a runtime field"]
Q3 -->|"No"| FD["Last resort: fielddata with a frequency filter and monitoring"]
Put your mapping decisions into index templates, so every new index is created the right way. Reviewing a template once is far easier than repairing mappings across hundreds of indices later.
20More Anti-Patterns and Mistakes to Recognise
These habits show up again and again in troubled clusters.
Problem
Aggregating on a text field with fielddata and expecting whole values, such as full names or cities, in the buckets.
Why It’s Harmful
The buckets contain individual lowercase tokens, so “New York” becomes two separate entries. Results look wrong, and the team spends time debugging a problem that is really a modelling error.
Correct Approach
Aggregate on a keyword sub-field, which keeps each value whole.
Problem
Disabling doc values on fields “to save disk” without checking whether any query will sort, aggregate or script on them later.
Why It’s Harmful
A field without doc values cannot be sorted or aggregated efficiently. If the requirement appears later, the only fix is reindexing, and a hurried workaround may involve fielddata or heavy scripts.
Correct Approach
Disable doc values only on fields that are certain to be used purely for searching or retrieval, and document the decision.
Problem
Running large aggregations across long time ranges and every index at once, with no limits on the number of terms or buckets.
Why It’s Harmful
Each shard must load supporting structures and hold partial results in memory. Combined, these can exhaust heap even when no single field looks unreasonable.
Correct Approach
Narrow queries by time range and index, cap the number of returned buckets, and pre-aggregate data for dashboards that repeat the same heavy question.
Problem
Running with far too many small shards, each of which carries its own segments and its own fielddata or ordinals structures.
Why It’s Harmful
Per-shard overhead multiplies. Even modest fielddata per segment adds up across thousands of shards, and the heap is quietly drained.
Correct Approach
Size shards sensibly, use lifecycle policies to roll over and consolidate old data, and avoid creating a new index per tiny tenant or per day when volumes are small.
21Security and Operational Considerations
Memory-heavy features are also an availability risk, and availability is part of security.
Resource abuse as a risk
Anyone who can run aggregations on a field with heavy memory needs can, deliberately or accidentally, force nodes to load large structures. In a shared cluster, this makes fielddata-enabled fields a route for one team’s queries to degrade everybody else’s service. Restricting which roles can query which indices, and which fields are exposed, reduces the surface area. Circuit breakers help, but they are a last line of defence rather than a substitute for access control and good modelling.
Exposure of token-level content
Enabling fielddata on a text field makes it possible to list the individual tokens found in that field, along with counts. Depending on the content, such tokens could reveal sensitive words, names or fragments. Field-level and document-level security rules still apply in a secured cluster, but you should think about whether allowing token-level aggregation on a field is appropriate before enabling it, especially for fields containing personal or confidential text.
Operational discipline
Review mapping changes
Treat enabling fielddata like a change that needs review, with a written reason and a memory estimate.
Load test before launch
Run realistic queries against realistic data volumes on a staging cluster and watch the heap.
Separate workloads
Put heavy analytical workloads on their own nodes or clusters, so they cannot harm user-facing search.
Set query limits
Use bucket limits, timeouts and sensible defaults in applications to bound the cost of any single request.
Fielddata memory persists after the query that created it ends. A single expensive query can leave a large footprint that lasts until the segment is gone or the cache is cleared, so the harm is not limited to the moment of the request.
22Fielddata in Managed, Cloud and Container Environments
Running Elasticsearch as a service or on containers changes who presses the buttons, not the physics of memory.
Managed services
Managed offerings, whether from Elastic or from cloud providers, take care of provisioning nodes, configuring the heap and applying upgrades. They do not, however, change how a mapping behaves. A text field with fielddata enabled will consume heap on a managed cluster exactly as it would on your own hardware. Managed services often include monitoring dashboards that show heap use, garbage collection and circuit breaker trips, which are precisely the signals that reveal fielddata trouble, so it pays to learn to read them.
A managed cluster’s instance sizes are often tied to heap sizes, which means that solving a memory problem by moving to a bigger instance has a direct and recurring cost. Since remodelling a field is a one-time effort, while larger instances are billed month after month, fixing the mapping is usually the cheaper path.
Containers and Kubernetes
When Elasticsearch runs in containers, the heap must fit inside the container’s memory limit, with room left over for the operating system’s file cache and other overheads. If the limit is too tight, the container may be killed by the platform when memory rises, which looks like a sudden crash. Because doc values rely on the file system cache, starving the container of non-heap memory quietly slows every aggregation even when fielddata is not in use.
Self-managed servers
You control heap and hardware. Follow the half-of-RAM guidance and keep room for the file system cache.
Managed cloud services
Heap is set for you by instance type. Monitor breaker trips and pause times, and remodel rather than upsizing blindly.
Kubernetes
Set memory requests and limits with headroom above the heap, and avoid overcommitting nodes that host Elasticsearch pods.
Local development
Small datasets hide the problem. Do not trust a laptop test to reveal production memory behaviour.
Tiered storage and node roles
Many clusters use tiers: hot nodes for fresh, busy data, warm and cold nodes for older data. Putting heavy aggregation workloads on the tier whose nodes have the most heap headroom, and keeping master-eligible nodes free of such work, is a sound structural choice. Data that is rarely queried should not be forced into memory-hungry structures at all, and the simplest way to ensure that is to avoid fielddata on it.
Memory is the most expensive resource in most Elasticsearch deployments. Every gigabyte of heap spent holding fielddata is a gigabyte not available for real work, and, in a paid cloud environment, a visible line on the bill.
23Advantages, Disadvantages and Trade-offs
Fielddata is a tool with a narrow sweet spot. Here is the balanced view.
Advantages
- Makes sorting and aggregation possible on analyzed text without changing the mapping
- Requires no extra disk space and no work at index time
- Can be enabled or disabled on an existing text field without reindexing
- Very fast once loaded, because everything is in memory
- Frequency filters let you load only the useful subset of terms
Disadvantages / Trade-offs
- Consumes heap memory that all other node work also needs
- The first request pays a large loading cost
- Results are token-based, which often surprises users
- Can trigger long garbage-collection pauses and node instability
- Memory is retained after the request and grows with data volume
- Better alternatives exist for nearly every common use case
Comparing the ways to get a document-to-value view
| Approach | Cost paid | Best used for |
|---|---|---|
| Keyword field with doc values | Extra disk at index time | Sorting, grouping and filtering on whole values |
| Text field with fielddata | Heap memory at query time | Token-level aggregation on a bounded dataset |
| Runtime field | CPU at query time | Occasional derived values, exploration |
| Text-aware aggregation for significant terms | CPU at query time on a sample | Finding unusual words in a set of results |
| Pre-aggregation or rollup at ingest | Extra processing at ingest | Dashboards that repeat the same heavy question |
Fielddata is not evil. It is a legitimate feature with a clear purpose. The mistake is using it as a default rather than as a deliberate, measured choice with a plan for monitoring.
24Real-World and Industry Examples
Here is how the ideas play out in typical production settings.
E-commerce catalogue
An online store lets shoppers search product titles and also filter by brand and sort by name. The title is a text field for searching, while the brand and a sortable version of the title are keyword fields. Nothing in the system needs fielddata, and heap usage stays flat as the catalogue grows.
Centralised logging
A platform team stores millions of log lines per hour. The message is a text field for searching, while service name, log level and host are keyword fields for dashboards. A recurring dashboard that once grouped by a text field caused heap alarms until it was rewritten to use keyword fields.
Customer feedback analysis
A product team wants the most common words in free-text reviews for a quarter. They use a specialised text aggregation on a filtered subset, rather than enabling fielddata on the whole review field for every index.
Security analytics
Security teams aggregate on fields such as user names, IP addresses and event types. These are modelled as keyword and IP fields with doc values, giving fast aggregations without large heap costs, which matters when investigations run heavy queries during incidents.
Migration from old versions
A company upgrading from a very old release finds that dashboards depended on analyzed string fields being aggregated directly. During the upgrade, they add keyword sub-fields, reindex, and update the dashboards. Afterwards, the clusters use less heap and behave more predictably.
The lesson across all these examples
In each case, the healthy design separates the two jobs of a string: being found, and being grouped or ordered. Text fields do the first job, and keyword fields do the second. Whenever a system tries to make one field do both jobs through fielddata, it pays in memory. Whenever it models both jobs explicitly, it pays a small, predictable disk cost instead.
25Common Myths About Fielddata
A few persistent misunderstandings cause a surprising share of the trouble, so let us clear them up.
Myth: “Fielddata is what makes aggregations work in Elasticsearch.”
Reality: for nearly all field types, aggregations run on doc values, not fielddata. Fielddata is only relevant for analyzed text fields where it has been deliberately enabled.
Myth: “Enabling fielddata is a harmless setting change.”
Reality: it changes nothing until queries use it, and then it can consume large amounts of heap that stay allocated. The harm is delayed, which is exactly why it is so easy to underestimate.
Myth: “A bigger fielddata cache size makes things faster.”
Reality: by default the cache is unbounded. A size limit only causes eviction. Speed comes from having the structure loaded, not from configuring a larger limit.
Myth: “Keyword sub-fields double my memory usage.”
Reality: they add disk space and some index-time work, but their doc values are read through the operating system cache, not the heap. They typically cost far less memory than fielddata would.
Myth: “Turning fielddata off frees memory instantly.”
Reality: memory is released when segments go away, entries are evicted or the cache is cleared. Turning the setting off only prevents new loads.
Myth: “If the breaker trips, the node is broken.”
Reality: the breaker doing its job means the node is protected. The failed request is the price of keeping everything else alive. The right response is to reduce demand.
Myth: “More RAM always fixes fielddata problems.”
Reality: heap size has a practical ceiling, and bigger heaps can bring longer garbage-collection pauses. Remodelling data is usually more effective than adding memory.
26How This Topic Evolved Across Versions
A short history explains why so much older advice online looks different from current practice.
Early releases
String fields were analyzed by default, and fielddata was the main way to sort and aggregate. Memory problems were a leading cause of cluster instability.
Doc values arrive
Doc values were introduced as an optional, on-disk alternative, letting the operating system cache do the work instead of the heap.
Doc values become the default
In the 2.x series, doc values were turned on by default for fields that are not analyzed, making the safer path the automatic one.
Text and keyword split
Version 5.0 introduced separate text and keyword types and disabled fielddata on text fields by default, making the memory cost a deliberate choice.
Better protections and tools
Later releases improved circuit breakers, including memory-aware parent breakers, and added runtime fields and text-aware aggregations, giving users more ways to avoid fielddata.
Many blog posts and forum answers were written for versions where fielddata was on by default. Advice such as “just increase the fielddata cache” or “warm the fielddata at startup” belongs to that era. Always check which version an answer was written for before following it.
27Frequently Asked Questions
Short answers to the questions people ask most often about fielddata.
It is an in-memory, document-to-terms structure that Elasticsearch builds by flipping the inverted index of a field, so that sorting, aggregations and scripts can read each document’s values quickly.
Because analyzed text fields have no doc values, so the only way to sort or aggregate on them is fielddata, which lives in the heap and can consume a lot of memory. The message nudges you toward a keyword field.
Keyword fields use doc values for sorting and aggregations, not classic fielddata. However, aggregations on keyword fields can build global ordinals in the heap, which are accounted for alongside fielddata in memory statistics.
Usually not. First try a keyword sub-field, which is the intended solution for whole-value sorting and grouping. Enable fielddata only when you really need token-level aggregation and have planned for the memory.
Because fielddata on a text field contains analyzed tokens. The analyzer split and lowercased your text, so the buckets are tokens rather than original phrases. Aggregate on a keyword field to get whole values.
Use the cat fielddata API for a quick table, the node or index statistics for exact numbers and evictions, and the breaker statistics to see limits and trips. Combine these with heap and garbage-collection metrics.
No. Already loaded structures stay in the cache until they are evicted, their segments are removed, or you clear the cache. After a mapping change, clear the fielddata cache to release memory promptly.
It estimates the memory a fielddata load would need and rejects the request if the total would exceed its limit, protecting the node from running out of heap. The failed request gets an error, but the node stays up.
It can help bound memory, but if the limit is smaller than the working set, entries are evicted and reloaded repeatedly, hurting performance. Any limit should also sit below the circuit breaker limit so eviction can act before the breaker trips.
Doc values are built at index time and stored on disk for most field types, while fielddata is built at query time in memory, mainly for analyzed text fields.
They are different structures, but they live in the same in-memory accounting. Global ordinals speed up aggregations on keyword-like fields, and their size depends on how many distinct values the field has.
Sorting on a text field with fielddata orders documents by tokens, which rarely matches what people expect for names or titles. A keyword sub-field, possibly with a lowercase normalizer, gives predictable whole-value ordering.
Use an aggregation designed for significant terms in text. It analyses the text of matching documents on the fly and highlights unusually frequent words, without requiring fielddata on the field.
28Summary and Key Takeaways
Fielddata is the in-memory, document-oriented view that Elasticsearch can build by flipping the inverted index of an analyzed text field. It exists because the inverted index answers “which documents contain this word” brilliantly but cannot answer “what does this document contain” without help. Since version 5.0 it has been disabled on text fields by default, because loading it consumes heap, delays the first request, produces token-level results that surprise users, and can push a node into long garbage-collection pauses and even out of the cluster. The dependable way to sort and aggregate on strings is to give them a keyword sub-field with doc values, leaving fielddata as a rare, monitored fallback. Understand the alternatives, watch the memory, respect the circuit breakers, and your cluster will spend its heap on serving users, not on flipping indexes.
Key Takeaways
- Fielddata flips the inverted index — it builds a document-to-terms structure in heap memory, at query time, so sorting, aggregations and scripts can read each document’s values.
- It is off by default on text fields — because it is costly in memory and produces token-level results; the error message is a safety feature, not an obstacle.
- Doc values are the preferred path — built at index time and stored on disk, they serve keyword, numeric, date and similar fields without burdening the heap.
- Use a keyword sub-field — search on the text field, sort and aggregate on the keyword version, and add a lowercase normalizer when case should not matter.
- Memory pressure is the real danger — large fielddata leads to long garbage-collection pauses, evicted nodes and cluster-wide instability, so treat it as an availability risk.
- Use the guard rails and watch the numbers — the fielddata and parent circuit breakers, cache size limits, frequency filters, and the cat, node and breaker statistics all help; never fix a breaker trip by simply raising the limit.
- Prefer better alternatives first — keyword fields, text-aware significant-term aggregations, runtime fields and pre-aggregation solve most needs, and index templates keep good modelling consistent across every new index.