One document per dish, typed by its mapping
text is analysed for matching; keyword stays exact for filters and facets. No joins, so copy the restaurant in.
Restaurant 77: veg Paneer tikka ₹280, non-veg Chicken roll ₹120. Search “veg under ₹150”.
The trap
It matches: object arrays flatten to veg: [true, false] and price: [280, 120]. One document per dish fixes it.
What does Elasticsearch promise, precisely?
Durable once acknowledged, searchable after the next refresh, real-time by ID. Atomic only per document.
Your primary database?
Bad: One store, no pipeline
No multi-document transactions or constraints; replicas copy a bad bulk delete in milliseconds.
Good: Beside the database
The database stays the truth; CDC feeds the index, rebuildable from scratch.
Data sets the primaries. Traffic sets the copies.
36 GB of dishes → 3 primaries of 12 GB. 12,000 shard searches/s, if a node benchmarks 2,000/s → 6 copies.
100,000
shards for 50,000 tenants, one index each
A node holds at most 1,000 non-frozen shards: at least 100 data nodes before any data. Share one index, routed by tenant_id.
Pick it, or not
- Pick: ranked text search with facets, geo or logs
- Not: the only copy, or transactions
- Not: a few hundred thousand rows in Postgres
- Not: points moving every few seconds, like riders
Say it like this
Elasticsearch for ranked text, facets and geo, never as the only copy. Postgres stays the truth, CDC and Kafka feed the index, and results lag a second or two.