Business
Business write frequency is quite low, but the read volume is much higher for search and view requests. We can consider a relational database, like PostgreSQL. To handle high read volume, we can create replicas
Geohash
Geohash stores business_id and its geohash prefix. We create this table because when we query businesses within the radius based on user's longitude and latitude, no matter how we index the fields, we have to scan the whole table. Therefore, we can use geohash to convert longitude and latitude to one-dimensional data. Considering it needs to support high read volume and low write volume, we can also choose a relational database as above.
In addition, as the radius is adjustable and geohash with different lengths presents different scopes, we can store geohashes with multiple lengths for the same business.
Another thing to be noted is we don't store a list of busiess_ids for the same geohash, because it will make updating or deleting businesses complicated, but in we can do a list of busiess_ids in cache to make read faster.
Review
Review has both high read and write volumes, so we can consider key-value database. We can partition it by business_id, and make reviewed_by and updated_at as sort keys. Also, to retrieve user's reviews by user, we can create GSI, and make reviewed_by as partition key and business_id & updated_at as sort keys.
Even we use geohash there're still some problems:
To resolve the above edge cases, we can calculate 8 neighbor geohashes and collect those businesses as well for further calculation and filtering
Explain any trade offs you have made and why you made certain tech choices...
Try to discuss as many failure scenarios/bottlenecks as possible.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?