Custom Similarity Modules in Elasticsearch
How Elasticsearch decides which documents "match best," and how to reshape that decision when the default formula does not fit your content — explained from the ground up with analogies, diagrams, and real production thinking.
Picture a legal research platform where searching for “breach of contract” returns a two-line email mentioning the phrase once, ranked above a detailed forty-page case ruling that discusses the same phrase eight times across a rich legal argument. Users complain the search feels broken, even though every technical part of the system is working exactly as designed. The problem is not a bug. It is that Elasticsearch’s default idea of “relevant” was tuned for typical web-style content, not dense legal documents where length and repetition mean something different.
The part of Elasticsearch responsible for turning “does this document match” into “how well does this document match, compared to every other match” is called similarity. A custom similarity module lets an engineer replace or tune that scoring formula for specific fields, aligning relevance with what actually matters for their particular content and their particular users. This article walks through similarity piece by piece: what it is, why the default exists, how scoring actually works internally, how to configure and tune it, and how to avoid the mistakes that turn a well-meaning tuning attempt into search results that feel worse, not better.
Every new term is explained the first time it appears, with an everyday analogy and a real production example, so no prior Elasticsearch knowledge is assumed. In keeping with how this topic is normally taught at the conceptual level, no code snippets are shown — the focus stays on what similarity does and how to reason about it, rather than on the exact configuration syntax.
1What Is a Custom Similarity Module?
A similarity module is the scoring formula Elasticsearch uses to decide how relevant a matching document is. A custom one lets that formula be swapped or tuned for a specific field.
Start with the plain-English definition
Elasticsearch stores information as JSON documents inside containers called indices, and uses a text search library called Lucene underneath to actually find and rank matching documents. When a search runs, Elasticsearch does not just find documents that contain the searched words — it also assigns each matching document a numeric relevance score, and returns results ordered from the highest score to the lowest.
Similarity is the name for the mathematical formula that turns raw signals, such as how often a word appears and how long a document is, into that single relevance score. Elasticsearch ships with a well-regarded default similarity, but that default embodies assumptions that do not fit every kind of content equally well. A custom similarity module is a named, configured alternative to the default, applied to one or more specific fields, tuned or entirely swapped out to better match a particular use case.
Think of a panel of judges scoring a cooking competition. The default judging rubric might weigh presentation heavily, which works well for a plating competition. For a home-style comfort food competition, a different rubric weighing flavor and portion generosity more heavily would produce fairer results. Similarity is the rubric. A custom similarity module is choosing, or rewriting, that rubric to fit the actual competition being judged.
Why this is a per-field setting, not a whole-cluster switch
Similarity is configured at the level of an individual field within an index’s mapping, not for the whole cluster or even the whole index at once. This matters because a single index commonly holds several very different kinds of text: a short product title, a long product description, and a set of customer reviews might all benefit from different relevance treatment, since short titles and long free-form reviews naturally behave differently in how word repetition and length should affect scoring.
The three jobs a similarity module handles
Term weighting
Deciding how much a matched word should count based on how common or rare that word is across the whole field.
Length normalization
Deciding how much a document’s overall length should reduce or preserve the impact of a matched word appearing in it.
Frequency saturation
Deciding how much additional benefit a word repeated many times in one document should keep providing, rather than growing the score without any limit.
A few numbers worth remembering
The big picture
Here is the whole story in one diagram. A search request matches certain documents. For each match, the relevant field’s configured similarity formula combines several raw signals into one score. Those scores are what determine the final ranking returned to the user.
flowchart LR Q["Search Query"] --> M["Matching Engine
finds candidate documents"] M --> S["Similarity Module
for the searched field"] S --> T["Term frequency signal"] S --> D["Document length signal"] S --> R["Term rarity signal"] T --> C["Combined Relevance Score"] D --> C R --> C C --> Out["Ranked Search Results"]
Read the diagram left to right. Matching finds which documents qualify at all. Similarity is the formula that decides how well each one qualifies, relative to the others. The three signals feeding it are explained fully in Chapter 3, and how they combine mathematically is covered in Chapter 5.
What a custom similarity module does not do
Similarity does not decide whether a document matches a query at all — that is the job of the query itself. Similarity only decides, among documents that already match, how they should be ranked relative to each other. It also does not replace business-driven ranking factors such as price or popularity; those are typically layered on afterward, as covered in Chapter 20.
2Why Similarity Tuning Exists: The Problem It Solves
A single default relevance formula cannot be equally right for every kind of content. Understanding where the default’s assumptions break down explains exactly why customization exists.
Four situations where the default assumptions strain
Very long or very short fields
Extremely long documents, such as full legal rulings, or extremely short ones, such as product titles, can be penalized or rewarded by length normalization in ways that do not match how a human reader would judge relevance.
Dense, technical content
Technical or legal writing that legitimately repeats key terms many times can be judged less generously than the repetition actually deserves, if saturation is tuned for casual prose instead.
Fielded or structured content
A field such as a product code or a controlled vocabulary tag behaves nothing like free-flowing prose, and can benefit from an entirely different or even disabled length-normalization behavior.
Highly specialized language
In a narrow domain where nearly every document shares the same specialized vocabulary, the notion of a “rare” versus “common” term behaves differently than it would across general web content.
The alternative nobody wants
Without the ability to tune similarity, a team facing a relevance problem like the legal research example at the start of this article would be left trying to work around it entirely through query-time tricks, such as manually boosting certain fields or awkwardly rewriting queries to compensate for a length penalty. These workarounds are fragile, have to be reapplied to every query, and never actually fix the underlying scoring behavior the way adjusting similarity directly does.
Trying to fix bad relevance purely through query tricks is like adjusting how loudly you shout a request rather than fixing a mistranslation in the instructions themselves. It might help a little, but the actual misunderstanding is still there, waiting to cause the same problem the next time.
A short history of relevance scoring in Elasticsearch
Classic TF-IDF era
Early Lucene, and therefore early Elasticsearch, used a scoring approach built directly on term frequency and inverse document frequency, described fully in Chapter 3.
Alternative models researched
Information retrieval research produced several competing scoring families, including probabilistic and language-model approaches, some of which Elasticsearch later exposed as selectable built-in similarities.
BM25 becomes the default
BM25, a refinement addressing some of classic TF-IDF’s weaknesses, particularly around length normalization and frequency saturation, became Elasticsearch’s default similarity.
Per-field configuration matures
Later versions solidified the ability to configure similarity per field, and to tune BM25’s own parameters, rather than only choosing between whole alternative formulas.
Search platforms in specialized domains, such as legal research, scientific literature, and technical documentation, commonly report needing similarity adjustments specifically because their content’s length and repetition patterns differ sharply from the general web content BM25’s defaults were tuned against.
3Core Concepts: Term Frequency, Document Frequency, and Length Normalization
Three foundational ideas appear inside nearly every similarity formula. Understanding them individually makes every later chapter’s formulas readable at a glance.
Term frequency: how often a word appears
Term frequency is simply a count of how many times a specific searched word appears within one particular document. All else equal, a document mentioning “breach of contract” eight times is generally considered more relevant to that phrase than one mentioning it only once. Nearly every similarity formula treats higher term frequency as a positive signal, though how strongly it counts, and where it stops counting for more, varies between formulas.
Inverse document frequency: how rare a word is
Document frequency counts how many documents in the whole field contain a given word at least once. A word appearing in nearly every document, such as “contract” on a legal platform, carries little distinguishing power, since it does not help tell documents apart. A rare word appearing in only a handful of documents is a much stronger, more distinguishing signal when it does match. Inverse document frequency flips this relationship into a score: rare words receive a higher weight, common words receive a lower one.
Imagine a teacher grading essays for how well a student engaged with a reading. If every single essay mentions “the author,” that phrase says nothing useful about any one essay. If only two essays out of thirty mention a specific, unusual argument from deep in the reading, that mention says a great deal about those two essays. Term frequency is how often a phrase shows up in one essay. Document frequency is how many essays it shows up in. Rare, meaningful mentions matter more than common, generic ones.
Length normalization: adjusting for document size
A word appearing three times in a fifty-word document is proportionally far more prominent than the same word appearing three times in a five-thousand-word document. Length normalization adjusts a document’s raw term-frequency signal to account for its overall length, so that longer documents are not automatically favored just because they contain more words and therefore more opportunities to match.
| Concept | What it measures | General effect on score |
|---|---|---|
| Term frequency | How often a word appears in this one document | Higher frequency generally increases the score, with diminishing returns |
| Inverse document frequency | How rare the word is across the whole field | Rarer words carry more weight than common ones |
| Length normalization | How long the document is overall | Longer documents are adjusted so length alone does not inflate relevance |
Why all three together, not just one
Using term frequency alone would let very long documents win purely by having more words. Using inverse document frequency alone would ignore how strongly a document actually discusses a topic versus mentioning it in passing. Length normalization alone says nothing about which words matched. Every practical similarity formula, including the ones covered in Chapter 7, is built from some combination of all three ideas, weighted and shaped differently.
A relevance score on its own has no fixed meaning — a score of twelve is not “good” or “bad” in isolation. Scores only mean something when compared to other scores from the same query, which is why similarity tuning is judged by whether the ranking order improves, not by whether the raw numbers look larger or smaller.
4Anatomy of a Similarity Configuration
Without showing configuration syntax directly, this chapter describes the pieces a similarity setup is built from, and how they fit together conceptually.
Configuring similarity resembles adjusting the settings on a camera before a shoot: choosing a base mode suited to the lighting, then fine-tuning one or two specific dials, such as exposure or focus sensitivity, rather than redesigning the camera itself from scratch.
The building blocks
A base similarity type
An existing formula family, such as the default or one of the alternatives covered in Chapter 7, chosen as the starting point for tuning.
Named parameters
A small number of adjustable values exposed by the chosen base type, such as how strongly length normalization applies, that reshape its behavior without inventing an entirely new formula.
A similarity name
A label given to the specific configured combination of base type and parameters, so it can be referenced from a field’s mapping.
Field mapping reference
The step that actually applies a named similarity configuration to one specific field, covered fully in Chapter 8.
Two ways to customize: tuning versus replacing
Most real-world customization is tuning: keeping a well-tested base formula, such as BM25, and adjusting one or two of its exposed parameters to better fit the content. A smaller number of cases call for replacing the formula entirely, either by choosing a different built-in alternative described in Chapter 7, or by writing an entirely custom scoring script, described in Chapter 18. Tuning is lower risk and covers the large majority of real relevance problems; full replacement is reserved for genuinely unusual scoring needs.
What gets configured at the index level versus the field level
| Configured where | What it defines |
|---|---|
| Index settings | The named, reusable similarity configurations available for use within that index |
| Field mapping | Which of those named configurations, if any, applies to this specific field |
This two-step structure means one named custom configuration, once defined at the index level, can be reused across several fields that share the same relevance needs, rather than having to be redefined separately for each one.
Giving a custom similarity configuration a clear, purpose-based name, such as one describing its intended use for long-form technical content, makes a mapping far easier to read months later than a name describing only its technical parameters.
5Internal Working: How Similarity Plugs Into the Scoring Pipeline
Following one search request from arrival to final ranking shows exactly where and how similarity does its work inside the broader query execution pipeline.
Step by step
The query is parsed and matched
Elasticsearch identifies which documents satisfy the query’s matching conditions at all, independent of how well they match.
Per-field statistics are consulted
For each matched field, Elasticsearch already maintains statistics such as how often each term occurs and how many documents contain it, built during indexing rather than recalculated per search.
The field’s configured similarity runs
The specific similarity formula assigned to that field, whether the default or a custom configuration, combines the term frequency, document frequency, and length signals into a raw score contribution.
Contributions are combined across clauses
If a query involves multiple matching conditions or multiple fields, their individual score contributions are combined according to the query’s own structure.
Results are sorted by final score
Documents are ordered from highest combined score to lowest, and that order is what gets returned to the user as the ranked result list.
sequenceDiagram participant Client participant Node as Coordinating Node participant Idx as Field Index Statistics participant Sim as Configured Similarity Client->>Node: Search request Node->>Node: Identify matching documents Node->>Idx: Read term and document frequency stats Idx-->>Node: Statistics Node->>Sim: Compute score per matching document Sim-->>Node: Relevance score Node-->>Client: Ranked results
Why statistics are precomputed, not calculated live
Recomputing how often every term appears across every document freshly on every single search would be far too slow to support real-time search. Instead, Elasticsearch maintains these statistics as part of each shard’s underlying index structure, updated incrementally as documents are added, updated, or removed, so similarity can consult them almost instantly at query time rather than scanning the whole dataset fresh each time.
Similarity runs per shard, then combines
Because an index is typically split across multiple shards, and each shard by default computes term statistics based only on the documents it personally holds, scores from different shards can be based on slightly different local statistics. This is usually a negligible difference at meaningful data volumes, but it explains why relevance scores are not always perfectly identical to a single-shard mental model, a point revisited in Chapter 9.
6Data Flow: From Indexing Through Query Time
Similarity’s story does not start at search time. It begins earlier, when documents are indexed and the statistics similarity depends on are first built.
The two-phase flow
Indexing time
As documents are indexed, Elasticsearch builds and continuously updates the term and document frequency statistics, and stores document length information, that similarity will later read.
Query time
When a search runs, similarity consults those already-built statistics to compute a score for each matching document, without needing to reprocess the raw text again.
flowchart TD A["Document indexed"] --> B["Term and document frequency stats updated"] A --> C["Document length recorded"] B --> D["Stats available for future queries"] C --> D E["Search request arrives later"] --> F["Similarity reads stats from D"] F --> G["Score computed per matching document"]
Why changing similarity does not retroactively rescore existing documents
Because the underlying statistics are already built and stored as part of the index structure, changing a field’s similarity configuration affects how future searches score matching documents, but it does not rewrite anything already stored on disk. Existing documents are scored using the new formula the next time a search runs, applied against their already-existing statistics; nothing about the documents themselves needs to change for a similarity update to take effect on the next query.
When a full reindex is actually needed
Because similarity is set in a field’s mapping, and mappings for an existing field generally cannot be changed in place, switching a field’s similarity configuration on a live index typically requires creating a new index with the updated mapping and reindexing the data into it, rather than modifying the setting directly on the existing index. Testing the change on a small, separate index first, before touching production, avoids an expensive and disruptive full reindex done purely for experimentation.
7Built-In Similarity Types in Depth
Chapter 2 mentioned that several alternative scoring families exist besides the default. This chapter walks through the most relevant ones individually.
BM25 (the default)
A refined probabilistic scoring formula balancing term frequency, inverse document frequency, and length normalization, with saturation built in so that endlessly repeating a word provides steadily diminishing benefit rather than unlimited score growth. It performs well across a very wide range of general content, which is exactly why it is the default rather than one option among equals.
Classic (TF-IDF)
The older scoring approach BM25 was designed to improve upon, still available for cases needing its specific, more linear behavior, though it generally handles document length and term-frequency saturation less gracefully than BM25 does.
Boolean similarity
A minimal similarity that essentially ignores frequency and length entirely, scoring matching documents based mainly on whether terms matched at all. This suits fields such as tags or codes, where the presence of a match matters far more than how many times it occurred or how long the field is.
DFR (Divergence from Randomness)
A family of models scoring relevance based on how much a term’s observed frequency in a document diverges from what would be expected if terms were distributed randomly, offering a different mathematical lens on the same underlying frequency signals.
LM Dirichlet and LM Jelinek-Mercer
Language-model-based similarities that frame relevance in terms of how likely a document’s own language model would be to generate the query terms, an approach that behaves differently from BM25 particularly for shorter documents.
Choosing among the built-in options
| Content type | Reasonable starting point |
|---|---|
| General prose, product descriptions, articles | Default BM25, likely with minor parameter tuning |
| Tags, codes, controlled vocabulary fields | Boolean similarity |
| Very long, dense technical or legal documents | BM25 with adjusted length-normalization strength, covered in Chapter 9 |
| Short fields such as titles | BM25 with reduced or disabled length normalization |
Most relevance problems attributed to “the wrong similarity” are actually solved by tuning BM25’s own parameters, described in the next chapter, rather than by switching to an entirely different formula family. Reach for an alternative formula only once tuning has genuinely been tried and found insufficient.
8Per-Field Similarity and the Interplay with Mappings
Similarity does not exist in isolation from the rest of a field’s mapping. How a field is analyzed and typed shapes what similarity even has to work with.
Similarity only applies to scored text fields
Similarity is relevant specifically to fields used for full-text matching, where relevance ranking is meaningful. Fields used purely for exact filtering, sorting, or aggregations generally are not scored the same way, since those operations care about exact values rather than degrees of textual relevance.
Analysis happens before similarity ever runs
Before similarity can compute anything, a field’s configured analyzer has already broken its text into individual searchable terms, a process called analysis. Similarity works with the output of that process — the resulting terms and their statistics — not with the original raw text. This means two fields sharing identical similarity settings can still score very differently if their analyzers treat text differently, for example by handling case, stemming, or synonyms differently.
If analysis is the process of chopping ingredients before cooking, similarity is the recipe that decides how to combine the chopped ingredients into a finished dish. Even the best recipe cannot fix ingredients that were chopped inconsistently beforehand, which is why analysis and similarity are best reviewed together, not in isolation from each other.
Multi-field setups and similarity
A common mapping pattern indexes the same underlying text multiple ways, for example as both a fully analyzed searchable field and a separate exact-match variant. Each of those separate underlying fields can be given its own similarity configuration independently, since they are technically distinct fields under the hood even though they originate from the same source value.
| Field type | Typical similarity relevance |
|---|---|
| Fully analyzed text field | Similarity is central; this is where most tuning happens |
| Exact-match keyword variant | Similarity rarely matters; these fields are usually used for filtering, not ranking |
| Nested or object fields containing text | Similarity still applies to the inner text fields individually, same as any other text field |
Introducing stemming, synonyms, or different tokenization to a field’s analyzer changes the actual terms similarity sees and counts, which can shift relevance behavior even if the similarity configuration itself never changed. A relevance change should always be checked against recent analyzer changes before assuming similarity itself is the cause.
9Performance and Scalability
Similarity computation is generally lightweight compared to matching itself, but a few specific choices can meaningfully affect search performance at scale.
Where the cost really goes
Per-document computation
Similarity’s formula runs once for every matching document in every relevant shard, so its cost is paid across the full candidate set, not just the final returned page of results.
Shard-local versus global stats
Using globally accurate statistics across all shards, instead of each shard’s own local view, adds a coordination step that costs more but can improve scoring consistency at larger shard counts.
Formula choice
Simpler formulas, such as boolean similarity, are cheaper to compute than more elaborate ones, though the difference is rarely the dominant cost in a typical search request.
Local versus global term statistics
Chapter 5 mentioned that each shard by default scores using its own local statistics. On an index split across many shards, with data not perfectly evenly distributed, this can occasionally cause a document to score noticeably differently than it would if the whole index were a single shard. Elasticsearch offers a way to request globally accurate statistics across all shards involved in a query instead, at the cost of an extra coordination round trip before scoring actually happens.
Judging a competition using only the entries seen at one regional venue, versus first collecting notes from every regional venue before scoring, produces different levels of consistency. The all-venues approach is fairer across the board but takes longer to organize before any scores can be finalized.
When this actually matters in practice
For most production indices with a reasonably large, evenly distributed document count per shard, the difference between shard-local and globally accurate statistics is negligible and not worth the extra coordination cost. It becomes more noticeable on indices with relatively few documents per shard, or where shards are unevenly sized, which is one more reason sensible shard sizing, covered in general Elasticsearch capacity planning, indirectly supports healthy relevance behavior too.
What an interviewer may ask
10High Availability and Reliability
Similarity configuration is part of an index’s mapping, which means its reliability story is closely tied to how mappings themselves behave across a cluster’s normal operation.
Similarity settings survive normal cluster events
Because a field’s similarity configuration is stored as part of the index’s mapping, which is itself part of the cluster’s persisted metadata, it survives node restarts, master elections, and shard relocations without any special handling. A node recovering a shard, or a newly elected master taking over, reads the same mapping and applies the same similarity behavior as before, with no separate configuration to lose or resynchronize.
What actually breaks scoring consistency
Mixed mappings after a partial migration
If only some indices in a group meant to be searched together, such as several time-based indices under one alias, are updated to a new similarity while others still use the old one, search results across the group can inconsistently blend two different scoring behaviors.
Version differences during a rolling upgrade
A built-in similarity’s exact internal behavior can shift slightly between major Elasticsearch versions as the underlying library evolves, meaning scores are not guaranteed to be perfectly identical before and after a major upgrade even with no configuration change at all.
flowchart TD
A["New similarity needed for a field"] --> B["Create new index with updated mapping"]
B --> C["Reindex data into new index"]
C --> D["Validate scoring on the new index"]
D --> E{"Results look correct?"}
E -->|"Yes"| F["Switch alias to new index"]
E -->|"No"| G["Adjust configuration and repeat"]
Reliability comes from consistent rollout, not just correct configuration
Switching similarity for some indices in a searched-together group but not others produces results that are harder to reason about than either the old or new behavior alone. Following the alias-swap pattern in the diagram above, and completing a rollout across an entire logical dataset at once, avoids this specific failure mode.
11Security Considerations
Similarity configuration carries a narrower security profile than many other Elasticsearch features, but a few considerations still matter, especially where scripted scoring is involved.
Similarity settings themselves are low-risk
Choosing a built-in similarity type or tuning its numeric parameters does not expose any new attack surface, since it does not touch the file system, the network, or other documents — it only changes how an existing, already-permitted operation calculates a number. The main consideration here is administrative: who is allowed to change index mappings at all, which is governed by the same general index-management permissions covering any other mapping change.
Scripted similarity needs the same care as any script
When similarity is customized through a scoring script rather than a built-in formula, covered in Chapter 18, that script runs inside the same sandboxed scripting environment used elsewhere in Elasticsearch. It carries the same considerations around who may submit scripts, and whether inline or only reviewed stored scripts are permitted, that apply to any other use of scripting in the cluster.
Information exposure through relevance behavior
In a narrow set of cases, particularly for platforms where document frequency statistics might indirectly hint at how many documents contain sensitive terms, teams building highly sensitive search applications consider whether relevance-related signals could leak information about restricted content. This is a specialized concern rather than a routine one, but worth being aware of in the specific case of a search platform where the mere existence or count of certain documents is itself sensitive.
Since similarity is set through the mapping, treating index mapping changes with the same access control and review process as other production configuration changes automatically covers similarity changes too, without needing a separate, special-cased security policy just for this one setting.
12Monitoring, Logging, and Metrics
Relevance quality is harder to monitor with a single numeric metric than something like latency, but several practical signals still help catch problems early.
What to watch
Click-through and engagement signals
If search analytics are available, a drop in clicks on top results, or a rise in users scrolling past the first page, often signals a relevance regression before anyone files a complaint.
Score explanation tooling
Elasticsearch’s explain functionality shows exactly how a specific document’s score was computed, which is invaluable for understanding why one result outranked another after a similarity change.
A fixed relevance test set
A saved set of representative queries with expected top results, checked automatically whenever similarity or analysis changes, catches unintended relevance regressions the same way a test suite catches code regressions.
Query latency
Watching latency around similarity changes, particularly if a switch to globally accurate statistics from Chapter 9 was made, catches any unexpected performance cost early.
Building a lightweight relevance test set
A practical starting point is collecting twenty to fifty real, representative queries from actual usage logs, noting which results a human reviewer considers genuinely best for each one, and rerunning that same set of queries after any similarity or analyzer change to see whether the expected top results still appear near the top. This turns an otherwise subjective judgment call into something that can be checked mechanically and repeatably.
flowchart LR
A["Saved relevance test queries"] --> B["Run against current similarity config"]
B --> C["Compare ranking to expected best results"]
C --> D{"Still matches expectations?"}
D -->|"Yes"| E["Safe to proceed"]
D -->|"No"| F["Investigate before rolling out further"]
Score explanations are detailed and verbose, well suited to investigating one specific puzzling result during debugging, but not something to be logged in bulk or watched continuously the way a numeric metric would be.
13Deployment and Cloud Context
Similarity behaves consistently across self-managed, Elastic Cloud, and Kubernetes-based deployments, since it is a mapping-level setting rather than an infrastructure one.
Full configuration control
Operators define and apply custom similarity configurations directly as part of their own index templates and mapping management process.
Same mapping-level feature
Custom similarity works the same way on Elastic Cloud as self-managed, since it is configured through ordinary index and mapping APIs rather than anything infrastructure-specific.
Declarative index templates
Index templates carrying similarity configuration can be managed as Kubernetes custom resources, keeping relevance tuning in version control alongside the rest of a deployment’s definition.
Index templates as the natural home for similarity configuration
Because new indices, especially in time-based data patterns, are often created automatically from a template, defining custom similarity configurations inside index templates ensures every newly created index in a series automatically inherits the intended relevance behavior, rather than needing similarity to be manually reapplied to each new index as it is created.
Because a similarity change on a live index generally requires the reindex-and-swap pattern from Chapter 10, most teams manage similarity configuration inside version-controlled index templates, applied through a deployment pipeline, so a relevance tuning change goes through the same review as any other mapping change.
14Design Patterns and Anti-Patterns
Years of production relevance tuning have surfaced patterns worth copying, and an equally memorable set of habits worth avoiding.
Patterns worth copying
Tune BM25 before reaching for an alternative formula
Most relevance problems are solved by adjusting BM25’s own parameters rather than switching to a different formula family entirely, as emphasized in Chapter 7.
Match similarity choice to field purpose
Free-flowing prose fields and short, structured fields such as tags rarely benefit from the same similarity treatment, so choosing per field rather than applying one setting index-wide respects how differently those fields actually behave.
Test on a small, isolated index first
Validating a proposed similarity change on a small copy of representative data, before committing to a full production reindex, catches problems while they are still cheap to fix.
Keep a relevance test set under version control
Treating a fixed set of representative queries and expected results as a real test asset, reviewed and updated over time, turns subjective relevance judgment into a repeatable check, as introduced in Chapter 12.
Anti-patterns to avoid
The problem
Changing similarity based on a single anecdotal bad search result, without checking a broader representative set of queries.
Why it fails
A fix aimed at one specific complaint can easily worsen relevance for many other, unrelated queries that were working fine, which only a broader test set, as covered in Chapter 12, would reveal.
The problem
Leaving a searched-together group of indices on inconsistent similarity settings after a partial migration.
Why it fails
As described in Chapter 10, this produces results blending two different scoring behaviors in ways that are confusing to diagnose and inconsistent for users.
The problem
Reaching for a fully custom scoring script when tuning an existing built-in similarity’s parameters would have been sufficient.
Why it fails
A custom script, covered in Chapter 18, is harder to maintain and generally slower than a tuned built-in formula, and should be reserved for genuinely unusual scoring needs rather than used as a first resort.
15Best Practices and Common Mistakes
A concise, practical checklist distilled from the chapters above, organized as habits to lean into and habits to actively avoid.
Do
- Start by tuning BM25’s own parameters before switching formulas
- Choose similarity per field, matched to that field’s actual content style
- Test changes on a small, isolated index before a full production reindex
- Keep a versioned, representative relevance test query set
- Use explain output to understand, not just guess at, a puzzling score
- Roll out similarity changes across an entire logical dataset consistently
Avoid
- Changing similarity based on one anecdotal complaint alone
- Applying the same similarity settings to every field regardless of content type
- Leaving a group of related indices on inconsistent similarity settings
- Reaching for a custom scoring script before trying built-in tuning
- Assuming a similarity change requires no reindex when the field mapping actually needs updating
- Skipping a regression check against a broader query set after a change
16Trade-offs: Precision, Complexity, and Maintainability
Every similarity decision trades one good thing for another. Naming the trade-off explicitly leads to better decisions than treating any single configuration as simply “correct.”
| Choice | What you gain | What you give up |
|---|---|---|
| Tuning BM25’s parameters | Targeted improvement with low risk and easy rollback | Limited to what BM25’s own formula shape can express |
| Switching to an alternative built-in formula | A genuinely different mathematical treatment of relevance | Less community familiarity and tuning guidance than BM25 |
| Boolean similarity for structured fields | Simple, predictable presence-based scoring | No ability to reward stronger or repeated matches within that field |
| Globally accurate cross-shard statistics | More consistent scoring across shards | Extra coordination cost on every affected query |
| Custom scoring script | Complete control over the scoring formula | Higher maintenance burden and generally slower than a built-in option |
There is no universally correct choice in this table — only the choice that fits a given field’s actual content, how much engineering effort a team can sustain around relevance tuning, and how much the specific relevance problem actually costs the business if left unaddressed.
17Real-World and Industry Usage Patterns
Similarity tuning’s design choices make far more sense once seen against how organizations actually use it to solve concrete relevance problems.
Legal and scientific research platforms
Platforms indexing long, dense documents, similar to the legal research example opening this article, commonly adjust length normalization so that thorough, lengthy documents are not systematically penalized purely for their length compared to shorter ones.
E-commerce catalog search
Retail search often applies different similarity treatment to short fields such as product titles versus long fields such as full product descriptions, since a title match usually deserves stronger weight than the same word appearing once in a long description.
Technical documentation search
Documentation platforms frequently tune frequency saturation so that a term repeated many times across a genuinely thorough technical reference page continues to receive meaningful credit, rather than saturating too early the way default settings tuned for shorter web content might.
Tag and metadata search
Platforms with heavily tagged or categorized content commonly apply boolean similarity to those specific tag fields, so that a document simply having a relevant tag matters more than how many times that tag happens to be repeated in its underlying data.
Across every one of these patterns, the common thread is the same: the default formula is a strong general-purpose starting point, and the organizations getting the most value from similarity tuning are the ones that identified specifically how their content differs from typical web content, then adjusted only the parameters that difference actually calls for.
18Advanced Topics: Scripted Similarity and Custom Plugins
For the rare cases where tuning an existing formula genuinely is not enough, Elasticsearch offers two deeper levels of customization.
Scripted similarity
A scripted similarity lets an engineer define a scoring formula directly, using Elasticsearch’s own scripting language, rather than tuning parameters of an existing built-in formula. This offers full mathematical control over how term frequency, document frequency, and length combine, at the cost of the same performance and maintenance considerations that apply to scripting generally, since the formula now runs as interpreted script logic rather than a highly optimized native implementation.
Tuning a built-in similarity is like adjusting the settings on a well-engineered stand mixer. Writing a scripted similarity is like building your own mixer from individual parts — it offers complete control over exactly how it works, but also full responsibility for making sure it works well, holds up under heavy use, and does not break in some situation nobody thought to test.