Elasticsearch is a search and analytics engine built on Apache Lucene. Distributed; document-oriented; queryable via JSON DSL. The dominant choice for full-text search in modern applications.
This page covers the fundamentals.
Elasticsearch stores JSON documents:
{
"id": "abc",
"title": "Hello World",
"body": "This is the content...",
"tags": ["intro", "tutorial"],
"published": "2026-04-26"
}
Documents are stored in indexes (collection of documents). An index is roughly equivalent to a database in SQL terms.
Each index is split into shards (for distribution) and replicas (for availability). The cluster distributes shards across nodes.
For small data: 1 shard + 1 replica is fine. For large data: many shards across many nodes.
Schema for documents in an index. Defines field types: text, keyword, date, number, geo, etc.
Important: text fields are analyzed (tokenized for search); keyword fields are exact-match only.
{
"title": {"type": "text"},
"tags": {"type": "keyword"},
"published": {"type": "date"}
}
Get the mapping right; changing it later requires reindexing.
Elasticsearch's query DSL is rich. Common patterns:
{ "match": { "body": "hello world" } }
Tokenizes the query; finds documents with the tokens.
{ "term": { "tags": "tutorial" } }
Exact match on keyword field. No tokenization.
{
"bool": {
"must": [{ "match": { "body": "hello" } }],
"filter": [{ "term": { "tags": "tutorial" } }],
"must_not": [{ "term": { "status": "draft" } }]
}
}
Combine queries. must affects scoring; filter doesn't.
Like SQL GROUP BY:
{
"aggs": {
"by_tag": {
"terms": { "field": "tags" }
}
}
}
Aggregations are powerful: histograms, percentiles, geo-distance, date ranges, etc.
The original use case. Fuzzy matching, stemming, relevance scoring.
ELK stack: Elasticsearch + Logstash + Kibana. Aggregate logs from many sources; query and visualize.
Note: Elastic licensing changes have led to OpenSearch (AWS fork). For new log workloads, evaluate both.
Aggregations + Kibana = real-time dashboards.
Native geo-types and queries. "Find restaurants within 5km of (lat, lon)."
Prefix and fuzzy queries support type-ahead UX.
Not ACID; not for primary data. Use a relational database.
Eventually consistent. Recent writes may not be queryable for a few seconds.
For a few thousand documents, Postgres full-text is much simpler. See FullTextSearchInPostgresql.
Use a relational database as primary; index into Elasticsearch for search.
Elasticsearch handles parent-child and nested poorly. SQL joins are better in a relational store.
Self-hosted: managing master nodes, data nodes, hot/warm/cold tiers.
Managed: AWS OpenSearch, Elastic Cloud.
For most teams, managed is the right choice.
Mapping changes require reindexing. The pattern:
Plan for this; it happens.
Elasticsearch is memory-hungry. JVM heap + OS file cache. Sizing depends on document count, query patterns, retention.
Common rule: keep heap to 50% of RAM, max 32 GB.
For logs/time-series: recent data on fast storage; older data on cheap storage.
Reduces cost while preserving searchability.
Elasticsearch scores results by relevance. The default scoring (BM25) works well; tunable for specific needs:
Search relevance tuning is its own discipline; iterate based on user behavior.
Wrong types prevent expected queries. Plan mappings up front.
Snapshots to S3 or equivalent. Test restoration.
Single-node cluster has no redundancy. At least 3 nodes for production.
Logs grow fast. Without retention, indexes balloon.
OOM kills cluster. Tune heap; monitor.
Index into ES from a primary store; don't make ES the source of truth.