Core flows
Proximity search
“Show me parking within 5 km” is the most frequent request we serve. PostGIS answers it exactly; a geohash-cell cache lets drivers who are near each other share one cached answer.
The query#
Each listing stores its position as a PostGIS geography point with a GiST index, so a radius search is an index scan, not a scan of every listing. Results carry the distance, price, rating and how many slots are free for the requested window.
GET /v1/listings?latitude=12.9716&longitude=77.5946&radius_km=5&amenities=ev&sort=distance# radius defaults to 5 km, at most 25 km; up to 200 resultsSharing a cache between nearby drivers#
Caching by exact coordinates is useless: no two phones send the same GPS fix. We cache by geohash cell instead. The cell query covers the requested radius plus the cell's half-diagonal, so it contains every listing any driver in that cell could see. Each request then filters and re-measures the cached candidates against its own position, so answers stay exact.
Swipe sideways to see the whole figure.
def cell_for_search(latitude, longitude, radius_m, max_error_ratio) -> Cell: """Coarsest cell whose half-diagonal is at most max_error_ratio of the radius (coarser cells = more cache sharing; the extra area is filtered out per request).""" for precision in range(1, 10): cell = decode_cell(encode(latitude, longitude, precision)) if cell.half_diagonal_m <= radius_m * max_error_ratio: return cell return decode_cell(encode(latitude, longitude, 9))Request flow#
Pick the cell
geo.pyCache hit
RedisCache miss
PostGISFilter for this driver
Sort and respond
Keeping results fresh#
| Event | What happens to the cache |
|---|---|
| Listing created, edited, paused or deleted | The search namespace version is bumped (one Redis INCR); every older key becomes unreachable and expires on its own |
| Time passes | Entries expire after 30 seconds, which bounds how stale availability can be |
| Redis unavailable | Search falls through to PostGIS, slower but still correct |