1 Architecture & Apache Lucene Internals
Inverted Index & Postings
Rather than scanning text document by document, Lucene maps every unique token to a sorted list of document IDs (postings list), term frequency (TF), and term positions. Enables sub-10ms lookups across billions of documents.
Immutable Segments
An index is composed of multiple immutable Lucene segments written to disk. Documents are never updated in-place; updates write a new document and flag the old ID in a bitset (.del file). Background threads periodically merge smaller segments into larger ones.
Shards & Write Path
An index is partitioned into Primary Shards and replicated into Replica Shards. Writes route via hash: shard = hash(_routing) % num_primaries. The primary writes to memory buffer & Translog (WAL) before replicating to replicas in parallel.
Node Roles & Topologies
Production clusters separate workloads: Master-eligible (cluster state & quorum), Data nodes (hot/warm/cold shard storage & search), Coordinating nodes (scatter-gather request routing), and Ingest nodes (pre-processing pipelines).
Doc Values & Columnar Store
While the inverted index optimizes search, sorting, aggregations, and script lookups require Doc Values. Doc Values store document-to-field values in an on-disk columnar format mapped into the OS filesystem page cache to avoid JVM heap pressure.
Near-Real-Time (NRT) Refresh
By default, Lucene opens newly written in-memory segments to search every 1s (the refresh interval). Commits (fsyncing Translog to disk) happen every 30 minutes or when Translog hits 512MB, decoupling search visibility from disk I/O cost.
Analyzers & Tokenizers
Text processing pipeline: Character Filters (strip HTML, replace regex), Tokenizer (split whitespace, words, n-grams), and Token Filters (lowercase, stopwords, stemming, synonyms). Custom analyzers power search precision.
BM25 Scoring Formula
Best Matching 25 is the default full-text relevance ranking. It calculates score using Term Frequency with saturation parameter k1=1.2 and Inverse Document Frequency normalized against document length with parameter b=0.75.
2 Elasticsearch vs. OpenSearch: In-Depth Comparison
The 2021 License Fork & BeyondHistory & Context: Why the Fork Happened
In early 2021, Elastic NV relicensed Elasticsearch and Kibana from Apache 2.0 to the Server Side Public License (SSPL) and Elastic License v2 to prevent cloud providers (specifically AWS) from offering managed Elasticsearch without commercial contribution. In response, Amazon Web Services (AWS) along with a consortium of community contributors forked Elasticsearch 7.10.2 and Kibana 7.10.2 to establish OpenSearch and OpenSearch Dashboards under the permissive Apache 2.0 license. Today, both projects have diverged significantly with distinct feature sets, vector implementations, and cloud ecosystems.
3 Quickstart & Docker Compose Setups
⚡ Elasticsearch 8.x + Kibana
Dev Single-NodeSpin up an Elasticsearch 8 container with Kibana dashboard on localhost (security disabled for rapid local prototyping):
http://localhost:9200
UI: http://localhost:5601
🔍 OpenSearch 2.x + Dashboards
Apache 2.0Spin up an OpenSearch 2 node with k-NN plugin and OpenSearch Dashboards (security disabled for local dev):
http://localhost:9200
UI: http://localhost:5601
Elasticsearch 8+ enforces official client headers, while OpenSearch requires its dedicated SDK.
4 Hands-On Code Examples (Full-Text, Vectors & RAG)
1. Custom Mappings with Edge N-Gram Autocomplete & dense_vector
REST API / JSON DSL2. Production Python: Hybrid Search with Reciprocal Rank Fusion (RRF)
elasticsearch-py & OpenAI3. Exposing Search as an Autonomous Agent Tool
ReAct / Function CallingAgents query search clusters dynamically. When structured filters (e.g. date ranges, categories, tenant isolation) are combined with natural language semantic recall, hallucinations are eliminated:
5 Interactive Sharding & Cluster Sizing Calculator
🧮 Production Capacity & Shard Planner
Calculate exact primary shards, replica allocations, storage footprint, and required JVM heap memory based on industry best practices (30GB–50GB shard limit, max 31GB heap with Compressed OOPs).
6 Index Lifecycle Management (ILM / ISM)
Active index ingestion and recent query reads. High CPU and fast NVMe SSD storage. Rollover triggered after 50GB or 30 days.
Read-only indices. Ingestion stops. Trigger _forcemerge to 1 segment per shard and shrink replica counts to reclaim cluster memory.
Infrequently queried historical logs. Backed by Searchable Snapshots (Elasticsearch) or UltraWarm / Cold Storage in AWS OpenSearch, slashing storage costs by 80%.
Automated deletion after compliance retention window (e.g., 90 or 365 days). Safely removes shards from cluster state without manual operator intervention.
7 Production Tuning & Performance Checklist
The 50% & 31GB JVM Heap Rule
Never allocate more than 50% of physical RAM to JVM heap. The other 50% must remain available for the OS kernel page cache to hold Lucene segment files. Always cap heap at < 31GB to maintain 32-bit Compressed Ordinary Object Pointers (Compressed OOPs).
Bulk Ingestion Tuning
During initial massive backfills: temporarily set "index.refresh_interval": "-1" and "index.number_of_replicas": 0. Batch requests in chunks of 5MB–15MB or 1,000–5,000 documents using the Bulk API.
Disk Watermark Safeguards
Elastic/OpenSearch halts operations when disks fill up: Low watermark (85%) prevents allocating new shards; High watermark (90%) moves existing shards; Flood stage (95%) locks indices into read-only mode (read_only_allow_delete).
Filter Context vs. Query Context
Use filter clauses instead of must when relevance score is not needed (e.g. status codes, tenant IDs, timestamps). Filters bypass Lucene BM25 scoring arithmetic and are automatically cached in node memory bitsets.
Avoid Deep Pagination (search_after)
Never page past 10,000 results using from: 10000, which triggers massive coordinating node heap exhaustion as every shard must sort from + size documents. Use search_after with a Point in Time (PIT) cursor for deep exports.
Fielddata Trap
Never enable fielddata: true on analyzed text fields to perform aggregations or sorting. Fielddata builds in-heap un-inverted structures that cause catastrophic JVM Out-Of-Memory (OOM) crashes. Use multi-field keyword sub-fields with Doc Values instead.
8 Frequently Asked Questions
Can I migrate from Elasticsearch 7.10 directly to OpenSearch? →
How does Elasticsearch's ELSER compare to OpenSearch's Neural Search? →
Why should I use Elasticsearch/OpenSearch for vectors instead of Pinecone or Qdrant? →
What is the maximum number of shards a node can hold? →
Why does Lucene require 50% of RAM for OS Page Cache? →
mmap) to access inverted index postings, term dictionaries, and Doc Values directly from the operating system kernel's file cache. If JVM heap is configured too large (e.g. 90% of RAM), the OS cannot cache Lucene segments in RAM, forcing the kernel to read segments from physical disk on every query, which degrades p99 latency by orders of magnitude.