Elasticsearch is a distributed search and analytics engine built on Apache Lucene. It analyses the JSON documents you send into an inverted index plus structures for range and geo filters, and answers a query by asking every shard for its best hits and merging them. In an interview it is the default answer to “search, filter and rank millions of things by text, with facets, typeahead or distance, in milliseconds”, as long as you put it beside your database and say how the two stay in sync.
This one-pager tracks Elasticsearch 9.5 (current docs, October 2026); the internals live in the search engines series, linked from each section.
Picture it first
A big mall’s office keeps the official register of its 300 shops. At the entrance, a help-desk clerk answers shoppers from a card cabinet: each shop has a card filed under every word that matters (“momos”, “veg”, “kids’ shoes”) and a pin on a floor map.
When the office changes the register, a peon carries the change slip to the desk. The clerk writes the new card at once but drops it in a tray, emptied into the cabinet every second. Ask for “veg momos near gate 3” and she hands you five shop numbers, best first; you still walk to the shop for today’s price. The cabinet has four drawers, and a second-floor desk keeps a copy of each. If the cabinet burns, she rebuilds it from the register.
Map it back: the register is the database, the source of truth; the peon is CDC and Kafka; a card is a document; filing under every word is the inverted index; the tray emptied each second is the refresh; the pin is a geo_point; drawers are shards, the second-floor copy a replica; walking to the shop is hydrating from the database; rebuilding is a reindex.
Data model: indices, documents, mappings
An index is a named collection of JSON documents sharing one mapping, the schema that says how each field is indexed. Each document has an _id and keeps its original JSON as _source. There are no tables or query-time joins: one document is one search result. The field types to name:
text: analysed into terms (split, lower-cased, optionally stemmed) for full-text matching and BM25 scoring (part 2).keyword: the exact value, with column-oriented doc values for filters, sorting and facet counts.- Numbers,
date,boolean: range filters and sorting. geo_point,geo_shape: a location, or an area such as a delivery zone.dense_vector: embeddings for kNN search, up to 4,096 dimensions (dense vector).
The running example is a Swiggy-style food-delivery app, with one document per dish:
PUT dishes_v1
{
"settings": { "number_of_shards": 3, "number_of_replicas": 1 },
"mappings": {
"dynamic": "strict",
"properties": {
"name": { "type": "text", "fields": { "raw": { "type": "keyword" } } },
"suggest": { "type": "search_as_you_type" },
"cuisine": { "type": "keyword" },
"veg": { "type": "boolean" },
"price": { "type": "integer" },
"restaurant": {
"properties": {
"id": { "type": "keyword" },
"name": { "type": "text" },
"location": { "type": "geo_point" },
"rating": { "type": "half_float" },
"is_open": { "type": "boolean" }
}
}
}
}
}
Three rules follow. You can add fields but not change a field’s type or analyser without a reindex, so applications talk to an alias (dishes) that you repoint atomically. Turn dynamic mapping off for anything sellers supply: every unseen key becomes a field, and the index rejects documents past index.mapping.total_fields.limit, 1,000 by default, objects and multi-fields included (mapping limits). And an update rewrites the whole document: segments are immutable, so a price change is a delete plus a re-add (part 3).
Each index has primary shards, 1 by default and fixed at creation, each with replicas, 1 by default and changeable any time (index settings). A document goes to shard hash(_routing) % number_of_shards, where _routing defaults to _id. Timestamped, append-only data such as logs goes into a data stream, one name over a series of hidden backing indices. Part 5 covers masters, routing and replication.
Modelling documents for search
Interviewers probe this more than internals. The rule: model for the query, not the entity. Decide what one search result is, make that a document, and copy in everything you filter, rank or display.
Denormalise, and pay at write time
In Postgres a dish row points at its restaurant and its rating summary. The indexer joins them once, on write, so “paneer tikka near me, open now, rated 4+” reads one document per hit (Fig. 1, top).
You gain query speed: no joins, every filter checked inside one document. You pay in write fan-out: when Dilli Darbar closes for the night, all 60 of its dish documents need updating. Fine for an is_open flag that flips twice a day; wrong for exact stock or rider ETAs, which you read for the 20 results you render (data modelling and denormalisation).
Arrays of objects: object, nested or join
Put the dishes inside one restaurant document instead, and the default object mapping flattens the array into parallel lists, losing which values belonged together (nested field type).
| Object array | nested |
join (parent/child) |
One document per dish | |
|---|---|---|---|---|
| Fields from different dishes mix | Yes | No | No | No |
| Lucene docs for 1 restaurant, 60 dishes | 1 | 61 | 61, all on one shard | 60 |
| Changing one dish | Reindex the restaurant | Reindex the restaurant and all 60 dishes | Reindex that dish | Reindex that dish |
| Query cost | Lowest | nested query: moderate |
has_child: highest |
Low |
| Use it for | Arrays never matched in pairs | Small arrays queried as units | Few parents, many fast-changing children | The thing users search for |
Elastic’s join field page itself says to denormalise rather than replicate a relational model. Nested is capped by default at 100 nested mappings per index and 10,000 nested objects per document.
text or keyword
“Paneer tikka” as text matches “tikka paneer”; as keyword it matches only the exact string, but can be sorted and counted. Names need both, via a multi-field (name plus name.raw). IDs, enums and tags are keyword only: a facet like “North Indian (342)” on text needs fielddata, off by default.
One index per tenant, or one shared index?
When each B2B customer searches only its own documents, per-tenant indices give isolation and easy deletion, but cost shards. A node holds at most 1,000 non-frozen shards and masters need 1 GB of heap per 3,000 indices (size your shards), so 50,000 tenants × (1 primary + 1 replica) = 100,000 shards need at least 100 data nodes before any data. So share an index: add a tenant_id keyword, route with routing=tenant_id, and enforce the filter in a filtered alias or the API. Give the largest tenants their own index, the bridge model from tenancy models.
Guarantees, precisely
Near-real-time search. A write becomes searchable at the next refresh, which turns the in-memory buffer into a new segment every index.refresh_interval: 1 s by default, 5 s on Elastic Cloud Serverless. The catch: shards with no search or GET for 30 s (index.search.idle.after) skip background refreshes, so the next search triggers one and waits. An explicit refresh_interval, even 1s, opts out (index settings).
Real-time GET. GET dishes/_doc/dish_9001 is real-time by default, “not affected by the refresh rate” (get API). Only search is near-real-time.
Durability. With the default index.translog.durability: request, a write is acknowledged only after the translog is fsynced on the primary and every allocated replica (translog). async fsyncs every 5 s and can lose acknowledged writes: fine for logs you can resend.
Replication. Primary-backup, not quorum: the primary forwards each operation to every in-sync copy and acknowledges when all have applied it; a failed copy is first dropped from the in-sync set by the master (reading and writing documents). Two copies survive one failure; one slow replica slows every write.
Atomicity. One document is atomic; nothing larger is. A bulk request is a batch, not a transaction: each item succeeds or fails alone.
Concurrency. For read-modify-write, send back the _seq_no and _primary_term you read as if_seq_no and if_primary_term; if the document changed since, you get 409 Conflict (optimistic concurrency control). An indexer copying from a database sends version_type=external with the row version instead, so a late or replayed event cannot overwrite newer data.
Read-your-writes. A seller renames a dish and searches for it. Your options:
refresh=wait_foron that write: the response waits up to a second for the next refresh. Past 1,000 waiting requests per shard it forces one (refresh parameter).refresh=true: refresh now. Instant, but it makes tiny segments that every search and merge pays for. Never on every write.- Read the edit from the database, or by GET, on the seller’s own screens. Usually the best answer.
Approximate or surprising. Scores use per-shard statistics, terms facets are top-N per shard, and hits.total is exact only to 10,000 by default (part 5). A search can see a write before it is acknowledged, and an isolated old primary can briefly expose writes that never will be: dirty reads. A failed shard still yields 200 OK with partial results and _shards.failed above zero. Copies at different refresh points can reorder pages unless preference pins a session to the same copies.
Not a system of record
No multi-document transactions, no constraints, reindexing for mapping changes, and replicas that copy a bad bulk delete within milliseconds. Keep the database as the truth, take snapshots, and be able to rebuild the index from scratch.
Keeping the index in sync with your database
“How does data get into Elasticsearch, and how stale can it be?” comes up in almost every search design. The standard answer, from part 4:
- Write to the database only. The menu service never calls Elasticsearch.
- Publish what committed. Change data capture reads the database log, or the service writes a transactional outbox row in the same transaction, so the event exists if and only if the row committed. It goes to a Kafka topic keyed by dish ID, keeping each dish’s changes in order.
- Index idempotently. The indexer joins in restaurant fields, sends
_bulkrequests of a few MB, and passes the row version as an external version. A replayed event gets 409 and is skipped: an idempotent consumer for free. Deletes are events too. - Query for IDs. The search API asks for the top 20 dish IDs, with text, geo and open-now filters.
- Hydrate from the truth. It reads price, stock and opening status for those 20 from the database; checkout re-checks.
The consistency gap is CDC lag plus the indexer’s batch window plus up to a second of refresh: with Fig. 3’s assumed numbers, about 1–3 s when healthy, minutes when the indexer falls behind. Alert on consumer lag in seconds. This is eventual consistency by design, and hydration hides most of it.
Why not dual-write? If the service saves to Postgres and then to Elasticsearch, a crash between the two leaves them disagreeing forever, and two concurrent updates can reach the index in the wrong order. CDC orders changes by commit; external versions reject the stale one.
Rebuilds. To change an analyser or the shard count, build dishes_v2 from a database snapshot, replay Kafka from the snapshot’s position, compare, and repoint the alias atomically; keep v1 for rollback. A nightly count per restaurant against the database catches silent drift.
How it scales
Primaries spread data and write load; replicas add read capacity and failover. A search goes to one copy of every shard, each returns its top from + size hits on one thread, and the coordinating node merges them and fetches only the winners (part 5). So:
- More primaries add per-query parallelism and fan-out overhead; the count is fixed without split, shrink or reindex.
- More replicas add queries per second, paid for in disk and indexing on every copy. Change them any time.
- Custom routing (
routing=city_id) sends a query that names the city to one shard, at the risk of a hot shard for Mumbai.
Sizing a cluster in an interview
Elastic’s guidance is 10–50 GB and under 200 million documents per shard (size your shards). Walk the back-of-envelope arithmetic out loud:
- Data. 400,000 restaurants × 60 dishes = 24 million documents. At an assumed 1.5 KB each on disk (measure yours), that is 36 GB per copy: three primaries of 12 GB and 8 million documents, inside the guidance, giving every query three threads.
- Traffic. A dinner peak of 4,000 searches/s × 3 shards = 12,000 shard searches/s. If a benchmark shows one 16-vCPU node handling 2,000 a second at 60% CPU, you need 12,000 ÷ 2,000 = 6 copies: 3 primaries × (1 + 1 replica), one per node.
- Memory. With 32 GB of RAM and a 16 GB heap, each node’s 12 GB copy fits in the page cache, keeping tail latency low.
Surviving a spike
An IPL final’s innings break or a Flipkart-style sale can triple traffic for twenty minutes. In order:
- Cache at the API, keyed by normalised query, geohash cell and filters, for 30–60 s: “biryani” in one neighbourhood repeats thousands of times. At a 50% hit rate, 12,000 searches/s becomes 6,000 (caching strategies).
- Add replicas before the event. 6,000 × 3 ÷ 2,000 = 9 copies: 2 replicas on 9 nodes. At the default recovery rate of 40 MiB/s per node, a 12 GB copy takes 12 × 1,024 ÷ 40 ≈ 307 s, about 5 minutes, so scale an hour ahead.
- Set a query budget: a search
timeout, cappedsizeand page depth, and a degraded mode without fuzziness and facets. Shed load with a rate limiter before the cluster does it with 429s. - Protect writes. If menu updates spike too, raise
refresh_intervalto 5 s for the duration.
Typeahead, geo, logs and vectors
Typeahead: three options
Elasticsearch offers three ways to complete a dish name as the user types:
- The
completionsuggester stores each input and its weight in a finite-state structure built for speed. It matches only from the start of an input (add “tikka masala” as a second input), supports fuzzy prefixes, and filters only through contexts such as a category or geo cell. The structure is entirely heap-resident and fastest on a single-shard index (suggesters). - A
search_as_you_typefield creates shingle subfields and an edge-gram_index_prefixfrom one mapping line; abool_prefixmulti_matchmatches words in any order and combines with any filter (search_as_you_type). - An edge n-gram analyser is the do-it-yourself version; its default gram lengths of 1 and 2 are “almost entirely useless”, says the tokenizer page, so you tune them and pay for the extra terms.
In an interview: completion over an index of popular queries; search_as_you_type for result typeahead that must respect location and opening hours. The typeahead design adds the in-memory trie.
Geo: restaurants near me
Map the location as geo_point and filter by distance; filters are not scored and can be cached:
GET dishes/_search
{
"size": 20,
"query": {
"bool": {
"must": [ { "match": { "name": "paneer tikka" } } ],
"filter": [
{ "term": { "restaurant.is_open": true } },
{ "geo_distance": { "distance": "5km",
"restaurant.location": { "lat": 12.9716, "lon": 77.5946 } } }
]
}
}
}
geo_distance matches a radius, geo_bounding_box a map viewport, and a geo_shape query tests delivery-zone polygons against the customer’s point. Sort by _geo_distance, or blend distance into relevance with a gauss decay. geotile_grid and geohash_grid aggregations bucket hits into map tiles for “23 restaurants here” clusters. Geospatial indexes compares the cell schemes. For points that move every few seconds, like riders, a refresh-based index is the wrong tool: use Redis GEO or an in-memory grid (proximity search).
Logs and observability
Logs are append-only and time-ordered, so they go into a data stream with index lifecycle management (ILM): roll over at 50 GB per primary shard or daily, move older indices through warm, cold and frozen tiers, and delete whole indices, never documents. Since 9.0, new logs-*-* data streams default to the logsdb index mode: up to 60% less storage for 10–20% more indexing cost in Elastic’s benchmarks (logs data streams). Put Kafka in front to absorb bursts; part 5 sizes the tiers.
Hybrid and vector search
A dense_vector field gets a quantised HNSW graph per segment, and a knn clause fused with a BM25 query by reciprocal rank fusion gives hybrid search in one engine. Choose it when you need keywords and filters beside semantics, and a dedicated vector database for billions of vectors and little else. Quote memory: part 4 puts 50 million 768-dimension embeddings at about 42 GB of page cache per copy with int8.
Limits and numbers
Defaults from the Elasticsearch 9.5 documentation (October 2026). Shard sizes are guidance; the rest are enforced limits or defaults.
| What | Number | Notes |
|---|---|---|
| Shard size | 10–50 GB, under 200 million docs | Guidance; roll time series over at 50 GB |
| Docs per shard, hard limit | 2,147,483,519 (2³¹ − 129) | Lucene’s; deleted and nested docs count |
| Shards per node | 1,000 non-frozen | cluster.max_shards_per_node |
| Primaries per index | Default 1, maximum 1,024 | Fixed at creation; replicas default 1 |
| Fields per index | 1,000 | index.mapping.total_fields.limit |
| Nested | 100 mappings; 10,000 objects per doc | Each object is a Lucene doc |
| Result window | from + size ≤ 10,000 |
search_after with a point in time beyond |
| Request body | 100 MB | http.max_content_length, bulk included |
| Refresh | 1 s (5 s on Serverless) | Skipped on shards idle for 30 s |
| Translog | fsync per request; async every 5 s |
Flush at 10 GB |
| Query clauses | Derived from heap and thread pool, at least 1,024 | max_clause_count ignored since 8.0 |
| Heap | ≤ 50% of RAM, under ~26 GB | Compressed oops; the rest is page cache |
| Disk watermarks | 85% / 90% / 95% | At 95% (100 GB free on big disks), indices on the node go read-only |
dense_vector |
4,096 dimensions | Quantised HNSW by default |
| Recovery | 40 MiB/s per node | 12 GB copy ≈ 5 minutes |
When to pick it, and when not
| Elasticsearch | OpenSearch | PostgreSQL full-text | Typesense / Algolia | Columnar log store (ClickHouse, Loki) | Dedicated vector DB | |
|---|---|---|---|---|---|---|
| Model | Lucene shards: inverted index, doc values, BKD, HNSW | Same; forked from Elasticsearch 7.10.2 | tsvector with a GIN index inside the database |
Typesense: RAM-first index; Algolia: hosted API | ClickHouse: compressed columns; Loki: labels indexed, chunks in object storage | ANN index plus metadata filters |
| Freshness | ~1 s refresh + pipeline lag | Same | Same transaction | Near real time; Algolia async, ms to seconds | Seconds; built for batched writes | Varies |
| Relevance | BM25, function scores, learning to rank, RRF | Same family, hybrid pipeline | ts_rank, no IDF |
Typo-tolerant ranking rules | Little: filters, scans, aggregations | Vector distance |
| Ops | High: JVM, shards, upgrades | High; AWS managed service | None extra | Low; none for Algolia | Medium | Low to medium |
| Licence | ELv2, SSPL or AGPLv3 | Apache 2.0, Linux Foundation | PostgreSQL (permissive) | GPLv3; proprietary SaaS | Apache 2.0; AGPLv3 | Varies |
| Pick it for | Text + facets + geo + hybrid at tens of millions of docs; log search | The same, with Apache 2.0 or Amazon’s service | Up to a few million rows, simple ranking | Small team; index fits RAM or the SaaS budget | Cheap, huge log and metric volumes | Billions of vectors, semantic only |
On licences: Elastic left Apache 2.0 for SSPL and the Elastic License in 2021, AWS forked 7.10.2 as OpenSearch, and Elastic added AGPLv3 in 2024 (licensing FAQ). Running Elasticsearch behind your own app is unaffected.
Pick Elasticsearch when users type words and expect ranked, typo-tolerant results with facets, when text meets geo or numeric filters, or when you search terabytes of logs.
Pick something else when:
- It would be the only copy. Keep a database underneath.
- You need transactions: seat inventory, payments. Use PostgreSQL.
- You only look up by key. Use a key-value store or Redis.
- A few hundred thousand rows live in Postgres already. Its full-text search needs no pipeline.
- Points move every few seconds, like riders. Use an in-memory geo index.
- It is pure analytics over billions of events: a columnar store is far cheaper.
Common interview usage
| Design problem | Elasticsearch’s role | Document and index design | The follow-up to expect |
|---|---|---|---|
| Product search for an online store | Full-text, facets, ranking | Doc per product; title text, brand keyword, coarse in_stock |
Price and stock churn; facet accuracy |
| Nearby places (Yelp) | Text plus geo filter and distance sort | Doc per place; geo_point, categories, rating |
Dense city centres; relevance versus distance |
| Food delivery (Swiggy) | Dish search near the user | Doc per dish, restaurant fields copied in; zones as geo_shape |
A restaurant closes: fan-out updates |
| Post search (Twitter) | Recent posts by keyword or hashtag | Time-based indices; doc per post | Viral write bursts; search only recent indices |
| Typeahead | Suggestions per keystroke | Popular-queries index with a weighted completion field |
Why not an in-memory trie? |
| Distributed logging | Search and aggregate logs | Data streams, ILM, logsdb, Kafka in front | Cost at 1 TB a day; why not Loki |
| Ticketmaster (BookMyShow) | Event discovery by name, city, date | Doc per event; venue geo_point, date, genre |
Seat availability never comes from the index |
| Reddit / news aggregator | Search posts or articles | Doc per post; recency decay, votes | Votes change constantly: batch updates |
| Job search (LinkedIn-style) | Jobs by skill, title, location | Doc per job; skills keyword, geo_point, salary |
Personalised ranking |
| RAG over company documents | Hybrid passage retrieval | Doc per chunk; text, dense_vector, ACL groups |
Permission filtering; re-embedding |
In the interview
Give Elasticsearch’s job in one line, with the pipeline and the read path: “Dishes are indexed from Postgres through CDC and Kafka, one document per dish with restaurant fields copied in; the search API filters by distance and open-now, takes the top 20 IDs, and reads price and stock from Postgres.” That answers the first three follow-ups before they are asked.
Going deeper: failure modes
- Silent drift. A dropped event or indexer bug leaves the index wrong without an error. Reconcile counts nightly, alert on lag, rehearse the rebuild.
- Expensive queries. A leading wildcard (
*tikka) walks the term dictionary, scripts run per document, and a scraper atfrom=9,980costs every shard 10,000 entries. Cap depth; usesearch_after(keyset pagination). - Hot shards. Routing by city or tenant puts Mumbai or the biggest customer on one shard. Give giants their own index.
- Oversharding. Daily 5-shard indices kept a year are 1,825 small shards. Roll over by size.
- Disk flood stage. At 95% disk, indices on that node turn read-only and the indexer fails. Alert before 85%.
- Heap pressure. Huge
termsaggregations, fielddata and big completion fields live on the heap; long GC pauses drop nodes. - Bulk rejections. A 429 means a full write queue: back off with jitter.
Cheat sheet
| Concept | Remember it as |
|---|---|
| Index → shard → segment | Documents → Lucene index → immutable files |
| Mapping | text to search; keyword to filter, sort, count; type changes need a reindex |
| Modelling | One document per search result; denormalise; nested for small arrays; avoid join |
| Visibility | Search after refresh (1 s; idle shards wait); GET by ID real-time |
| Durability | Acked = translog fsynced on primary and replicas |
| Atomicity | One document; bulk is not a transaction |
| Conflicts | if_seq_no + if_primary_term, or external versions; 409 |
| Read-your-writes | refresh=wait_for, or read from the database |
| Sync | DB → CDC/outbox → Kafka → indexer → alias; IDs from the index, facts from the DB |
| Sizing | 10–50 GB per shard; primaries from data, replicas from QPS |
| Typeahead, geo | completion or search_as_you_type; geo_point + geo_distance filter |
| Not for | System of record, transactions, moving points, pure analytics |
How to say it in the interview
“Postgres stays the source of truth; Elasticsearch is a rebuildable search index. Menu changes flow through CDC into Kafka, keyed by dish ID, and an indexer writes one document per dish with the restaurant’s name, location, rating and open flag copied in, using the row version as an external version so replays are harmless. The index has 3 primaries of about 12 GB and one replica, behind an alias. A search filters by
geo_distanceand open-now, ranks by BM25 with a rating boost, and returns 20 IDs; the API reads live price and availability from Postgres. Results lag writes by a second or two, which is fine for discovery; checkout re-checks everything.”
Why not use Elasticsearch as the primary database? No multi-document transactions or constraints, near-real-time search, and reindexing for mapping changes. If it holds the only copy, a bad bulk delete or broken mapping is data loss.
How stale can results be, and what do you do about it? CDC lag plus indexer batching plus up to a second of refresh: one to three seconds when healthy, minutes in a backlog. Hydrate volatile fields from the database, re-check at checkout, show sellers their own edits from the database, and alert on consumer lag.
How many shards and replicas would you create? Primaries from data: 36 GB at 10–50 GB per shard gives 3. Replicas from traffic: 12,000 shard searches a second at 2,000 per node needs 6 copies, so one replica. Before a spike, cache at the API and add replicas an hour ahead.
Restaurants with dishes: nested or separate documents? Separate dish documents with restaurant fields copied in: users search for dishes, and a dish update reindexes one small document. Object arrays cross-match fields; nested reindexes the whole restaurant on every dish change.
How would you build autocomplete?
A popular-queries index with a completion field weighted by frequency, rebuilt from logs every few hours, for suggestions. For results as you type, a search_as_you_type field with bool_prefix, so location and opening-hours filters still apply.
Where to go next
- How search engines work: the one-page tour.
- Search data structures and Disk I/O and durability for search: inverted indexes, BM25, segments and the translog.
- Choosing a search engine: the alternatives, sized at four scales.
- Elasticsearch in depth: masters, routing, sequence numbers, aggregations, data tiers.
- Change data capture and Kafka: the pipeline that feeds the index.
- Vector databases: when semantic search needs its own system.
- Design product search for an online store, Design typeahead and Design food delivery: Elasticsearch inside full designs.
References and further reading
- Elasticsearch documentation: General index settingselastic.coDefaults for number_of_shards and number_of_replicas, the 1,024-shard cap per index, refresh_interval (1 s, 5 s on Serverless), search-idle shards after 30 s, and max_result_window.
- Elasticsearch documentation: The refresh parameterelastic.cofalse, wait_for and true; why refresh=true creates tiny segments; the 1,000 refresh listeners per shard before wait_for forces a refresh.
- Elasticsearch documentation: Translog settingselastic.corequest durability fsyncs on the primary and every allocated replica before acknowledging; async every 5 s; 10 GB flush threshold.
- Elasticsearch documentation: Reading and writing documentselastic.coPrimary-backup replication to in-sync copies, two copies by default, dirty reads, and search returning partial results with 200 OK.
- Elasticsearch documentation: Optimistic concurrency controlelastic.coSequence numbers and primary terms per operation, and conditional writes with if_seq_no and if_primary_term.
- Elasticsearch documentation: Size your shardselastic.co10–50 GB and under 200 million documents per shard, one thread per shard per search, 1,000 non-frozen shards per node, 1 GB of master heap per 3,000 indices, and the 2,147,483,519-document Lucene limit.
- Elasticsearch documentation: Nested field typeelastic.coHow object arrays are flattened and cross-match, nested objects as hidden documents, and the 100-mapping and 10,000-object limits.
- Elasticsearch documentation: Suggesters (completion suggester)elastic.coThe completion field, weights, fuzzy prefixes, category and geo contexts, the heap-resident structure and the single-shard advice.
- Elasticsearch documentation: Geo-distance queryelastic.coRadius filters on geo_point and geo_shape fields, accepted point formats, and arc versus plane distance.
- Elastic: Licensing FAQelastic.coThe 2021 move to SSPL and the Elastic License 2.0, and AGPLv3 added as a third option in 2024.