Why Elasticsearch Exists
Elasticsearch is a distributed search and analytics engine built for querying large volumes of structured and semi-structured data quickly. It is commonly used for product search, log analytics, operational dashboards, document search, internal tools, monitoring, and read models built from events.
Teams adopt it not just to store data, but because they need fast full-text search, flexible filtering, relevance scoring, aggregations, and scalable query performance across large datasets.
The Core Data Model
There are four foundational concepts worth locking in early: index, document, field, and mapping.
- Document: one JSON object stored in Elasticsearch.
- Field: one key inside that JSON document.
- Index: a collection of related documents.
- Mapping: the schema-like definition describing how fields are indexed and stored.
{
"title": "Intro to Elasticsearch",
"author": "Rahul",
"views": 120,
"published_at": "2026-04-11"
}In this example, the whole JSON object is a document. Each key such as title or views is a field. The document may live in an index like blog_posts. The mapping would define that title is searchable text, views is numeric, and published_at is a date.
Dynamic Mapping and Why It Is Both Convenient and Dangerous
Dynamic mapping means Elasticsearch can see a new field in an incoming document, infer its type, and add that field to the index mapping automatically.
This is great for prototypes and early experimentation because you do not need to define every field upfront. But in production, it can create surprising field types, mapping conflicts, and uncontrolled growth in the number of mapped fields.
dynamic: trueautomatically adds new fields.dynamic: falseignores unknown fields for mapping.dynamic: strictrejects documents with unknown fields.
How to Think About Mapping Design
Mapping is one of the most important design choices in Elasticsearch because it controls how your data can be queried later. In practice, mapping design is query design done in advance.
- Define mappings explicitly in production rather than relying heavily on dynamic inference.
- Use
textfor full-text search andkeywordfor exact match, sort, and aggregations. - Map dates and numeric fields intentionally instead of letting them be guessed.
- Do not index fields you never search on because indexing has a storage and write cost.
- Watch for mapping explosion when documents carry too many dynamic keys.
text looks harmless at first, but later you discover that sorting and aggregating on those fields becomes awkward or impossible without a keyword view.Object vs Nested: One of the Most Important Elasticsearch Concepts
Arrays of objects are where many teams get their first serious Elasticsearch surprise. A plain object field looks intuitive, but arrays of objects are flattened internally in ways that can break the relationship between sibling fields.
{
"title": "Elasticsearch Basics",
"authors": [
{ "name": "Rahul", "role": "writer" },
{ "name": "Amit", "role": "editor" }
]
}If authors is mapped as a regular object, Elasticsearch can flatten the data conceptually into arrays like authors.name = ["Rahul", "Amit"] and authors.role = ["writer", "editor"]. A query for name = Rahul and role = editor may now match even though Rahul is not the editor.
A nested mapping preserves each array element as its own hidden sub-document, so the relationship between name and role stays intact.
- Use
objectwhen field relationships inside arrays do not matter. - Use
nestedwhen multiple fields must match within the same array element.
How Elasticsearch Is Used in Real Systems
In many production systems, Elasticsearch is not the primary transactional database. Instead, data is written into operational systems first, then copied or projected into search indices in a shape optimized for query speed.
Common patterns include:
- Product search where users type free-text queries plus filters like price, brand, and category.
- Log analytics for filtering events by service, latency, environment, and time range.
- Operational dashboards where agents search aggregated views across multiple microservices.
- Document search over contracts, articles, support tickets, or knowledge bases.
- Event-driven read models where the index is built from CDC streams or domain events.
Lucene: The Engine Under the Hood
Elasticsearch is built on top of Apache Lucene. Lucene is the low-level search library that actually handles inverted indices, term dictionaries, postings lists, scoring, segment files, and query execution.
Elasticsearch adds distributed systems capabilities on top of Lucene: clustering, shards, replicas, REST APIs, aggregations, index management, node coordination, and operational tooling.
The easiest way to think about the relationship is:
- Lucene is the storage and search engine library.
- Elasticsearch is the distributed database and API layer built around Lucene.
High-Level Elasticsearch Architecture
At a high level, an Elasticsearch cluster consists of nodes. Data is split into indices, and each index is broken into shards. A shard is a Lucene index. Primary shards accept writes, and replica shards copy data for redundancy and read scaling.
- Cluster: the full Elasticsearch deployment.
- Node: one running Elasticsearch instance in the cluster.
- Index: logical collection of documents.
- Shard: one partition of an index, backed by Lucene.
- Replica: a copied shard for resilience and search scaling.
When a search request arrives, Elasticsearch fans the query out to relevant shards, gathers the results, merges them, and returns a unified response.
How Updates Work Internally
An Elasticsearch update is usually not an in-place mutation of an existing Lucene document. Instead, the system commonly performs a read-modify-write cycle.
- Read the existing document source.
- Apply the partial update or script.
- Create a new full version of the document.
- Mark the old version as deleted.
- Index the new version.
The old document is not physically removed immediately. It is logically deleted and cleaned up later during segment merges.
How Elasticsearch Manages Contention for Updates
Elasticsearch handles concurrent updates with optimistic concurrency control rather than heavy locking. The key idea is simple: detect stale writes instead of blocking all writers up front.
Modern Elasticsearch uses sequence numbers and primary terms. If you read a document and then send an update with if_seq_no and if_primary_term, Elasticsearch can reject the update if someone else changed the document first.
This prevents lost updates in distributed systems and is especially useful when multiple workers, services, or retry loops can touch the same document.
Near Real-Time Search: Why Writes Are Not Instantly Searchable
Elasticsearch is near real-time, not strictly real-time. A write can succeed and still not be visible to search immediately because search visibility depends on a refresh.
A refresh makes recently indexed changes visible to search by opening the latest Lucene segments for search. By default, this often happens about once per second on active indices.
- A successful write means the data has been accepted and persisted appropriately.
- A refresh means the data is now visible to search.
GETby ID can often see fresh data sooner than a normal search query can.
What Happens During Huge Batch Writes
Large ingestion jobs usually use the bulk API. During a big batch load, Elasticsearch is not only writing documents. It is also buffering work, creating segments, refreshing periodically, and later merging segments in the background.
That means heavy writes can increase:
- CPU usage for indexing and merge work.
- Disk I/O due to segment creation and compaction.
- Memory pressure on both the client and the cluster.
- Search latency if search and ingestion compete on the same cluster.
A Good Strategy for Initial Backfill
For a first-time backfill, the goal is usually to maximize throughput without destabilizing the cluster.
- Create the index up front with explicit mappings.
- Use the bulk API rather than one-document-at-a-time indexing.
- Increase the refresh interval, or temporarily disable frequent refresh if search freshness is not needed.
- Optionally reduce replicas during a controlled one-time load, then restore them afterward.
- Send bulk requests with controlled concurrency rather than unbounded parallelism.
- Monitor latency, rejections, merge activity, heap, CPU, and disk I/O during the load.
- Restore normal settings, refresh, and validate counts and sample queries after ingestion finishes.
Many teams also backfill into a brand-new index and then switch an alias after validation. That makes cutover safer than loading directly into a heavily queried live index.
Why Bulk Size Tuning Matters
Bulk requests are a tradeoff. If batches are too small, request overhead dominates. If batches are too large, requests become slower, memory usage rises, failures hurt more, and retries get more expensive.
Engineers usually tune bulk size by payload size as much as by document count. A common starting point is a few hundred to a few thousand documents, often landing around 5 MB to 15 MB per request depending on document size and ingest complexity.
The right answer depends on document size, mapping complexity, pipelines, shard count, hardware, and concurrency. Bulk size and worker count must be tuned together.
Practical Guidance for Engineers Using Elasticsearch
- Model documents around the query path, not around normalized storage tables.
- Spend real time on mapping design before pushing production traffic.
- Be careful with arrays of objects and decide deliberately between object and nested.
- Expect updates to be more expensive than they first appear.
- Remember that search freshness depends on refresh behavior.
- Treat large ingestion as an operational event, not just a loop over writes.
- Monitor merge pressure, shard sizing, indexing latency, and rejected bulk requests.
Closing Thought
Elasticsearch is easy to start and deceptively deep to master. The simple part is storing JSON and running a query. The harder and more interesting part is understanding how Lucene, mappings, shard architecture, refreshes, optimistic concurrency control, and ingestion strategy shape correctness and performance.
Once you internalize those building blocks, Elasticsearch stops feeling magical and starts feeling like an engineering tool you can reason about confidently.