Searching near me
Illustrative exampleNumbers here are illustrative: round figures to reason with, not measurements.
The trap is the obvious index. Separate B-tree indexes on latitude and longitude each return a strip around the whole planet; the database either reads one strip and checks the other condition row by row, or builds a bitmap from each and ANDs them (PostgreSQL docs (opens in a new tab)). Either way the work grows with the places in two global strips, not with the places near the user.
Use an index built for location. With cells, every place is labelled with a small H3 cell, and a search looks up the user’s cell and the cells around it (H3 docs (opens in a new tab)), then keeps places within 1 km by exact distance. Looking only in the user’s own cell misses the pizzeria 20 m away across its edge. A PostGIS GiST index with ST_DWithin (PostGIS docs (opens in a new tab)) or Elasticsearch’s geo-distance query (Elasticsearch docs (opens in a new tab)) does the same job.
Searches don’t reach PostgreSQL. A shared cache holds every place in each small cell that matches the words and filters, whoever asked first. A request gathers the cells covering its circle, fills any missing cell from the search copy’s replicas in one batched query, then keeps places within its own radius and orders them from its own position, so users at opposite corners of a cell each get a right answer.
- The app sends the point, the words and the filters.
- The search service gathers the cells covering a 1 km circle from the cache.
- Missing cells come from the search copy’s replicas in one batch.
- Places within this user’s 1 km are ordered and the first page returned.
Read:Learn: Geospatial / proximity lookupLearn: Indexes and search fundamentalsLearn: Caching strategy
Check yourself
A place is 20 m from the user but in the next cell. Is it found?
Show answerHide answer
Yes: the search looks in the user’s cell and the cells around it, then checks the real distance.