Elasticsearch is a distributed search and analytics engine. In simple language, it’s a database that’s insanely good at two things: full-text search (“find me all blog posts mentioning wireless headphones”) and aggregations (“group these 10 million log lines by status code in 200ms”).
It’s built on top of Apache Lucene, stores data as JSON documents, and talks to us over a REST API. No SQL, no drivers — just HTTP and JSON.
Why not just use Postgres?
Postgres is great. But try running WHERE description LIKE '%headphones%' on 50 million rows — it’s painful. Postgres doesn’t pre-index every word in your text; Elasticsearch does, using something called an inverted index (we’ll cover that next).
Think of it like this: SQL is built for transactions and exact-match queries. Elasticsearch is built for “search this text, sort by relevance, aggregate the rest.”
- ACID transactions
- Joins, foreign keys
- Exact match queries
- LIKE '%word%' is slow
- Eventually consistent
- No joins (denormalize)
- Full-text + relevance
- Aggregations on the fly
- Flexible schema
- Good for OLTP
- Weak full-text
- Limited aggregations
When to reach for it
The three classic use cases:
- Search — product search on Amazon, code search on GitHub, autocomplete suggestions. Anywhere a user types into a box.
- Logs & observability — the “E” in the ELK stack (Elasticsearch + Logstash + Kibana). Apps push logs in, we slice and dice them in Kibana.
- Analytics — dashboards over big event streams. “Top 10 countries by signup last hour” across billions of events.
When NOT to use it
- As your primary source of truth for money/orders/users. It’s eventually consistent and not ACID. Keep transactional data in Postgres, mirror to ES for search.
- For relational joins. ES doesn’t really do joins — we denormalize.
- For tiny datasets. If you have 10,000 rows, Postgres with a GIN index is plenty.
The mental model
ES = Postgres + Lucene + horizontal scaling, talking JSON over HTTP.
# Index a document
curl -X POST "localhost:9200/products/_doc/1" -H "Content-Type: application/json" -d '
{
"title": "Sony WH-1000XM5 Wireless Headphones",
"price": 399,
"category": "audio"
}'
# Search it
curl -X GET "localhost:9200/products/_search" -H "Content-Type: application/json" -d '
{
"query": { "match": { "title": "wireless headphones" } }
}'
That’s the whole API surface — PUT, POST, GET, DELETE against indices. We’ll dig into how the magic works in the next notes.