1) Start with 100000 users
2) 2% of starting users are concurrent users = 2000 concurrect users per day
3) Start with 20000 locations
4) 5 review per location initially - 5 * 20000 reviews
5) Start with 7 requests per user per day
6) Start with users table of 212 bytes per record
7) Start with locations table of 417 bytes per record
8) Start with review table of 628 bytes per record
Estimations
1) RPS: 2000 users *per day * 7 req per day / 24 * 60 * 60 = 0,162 RPS
2) 2000 concurrect connections when usually 1 server can handle 1000 -> we need 2 servers
3) 20000 locations * 417 bytes * 365 = 2,835 Gb per year for locations
3) 100000 reviews * 628 bytes * 365 = 21,835 Gb per year for locations
3) 100000 users * 212 bytes * 365 = 7,235 Gb per year for locations
POST /v1/auth
GET /v1/user/profile
POST /v1/user
PATCH /v1/user
DELETE /v1/user
GET /v1/location/nearBy
GET /v1/location/search
GET /v1/location/review
DELETE /v1/location/review
DELETE /v1/location
PATCH /v1/location
POST /v1/location
POST /v1/location/review
POST /v1/location/rating
POST /v1/location/bookmark
User <|-- +UserPosition
User <|-- +UserBookmark
User : +int UserId INDEX
User : +String UserName
User: +String HasehdPassword
User: +String Email INDEX
User: +DateTime CreatedAt
UserPosition: +int UserId INDEX
UserPosition: +Coordinates Position INDEX
UserBookmark: +int UserId
UserBookmark: +int LocationId
Location <|-- +LocationRating
Location <|-- +LocationReview
Location : +int LocationId INDEX
Location : +Coordinates Position INDEX
Location : +String Name
Location : +DateTime CreatedAt INDEX
LocationReview : +int ReviewId INDEX
LocationReview : +int LocationId INDEX
LocationReview : +int UserId INDEX
LocationReview : +String Review
LocationRating : +float Rating
LocationRating : +int LocationId INDEX
SystemLog : +int LogId
SystemLog : +int UserId
SystemLog : +int LocationId
SystemLog : +int ReviewId
1) ApiGateway - reponsible for auth + load balancing incoming requests. Also includes rate limiter to prevent spam of requests
2) UserSerrvice. Service ot manage users, like create, delte, etc
3) Location servcie - responsible for storing and updating location info as well as serving nearest locations
4) Logging. Collects logs from all the subsystmes
5) Monitoring. Monitros the overall health of components
6) Geohash is the cash of the most frequent locations, keyed by location id and has an internal priority queue to sort locations based on ratings
For user account creation
1)User issues http request to api gateway
2)User requests gets forwarded to a user service instance
3)User service makes a db query and returns result
Get nearby locations
1) user issues an http request to api gateway
2) user requests gets forwarded to a locaiton servcice
3) location service uses in meomry geohashing db to get nearby locations based on user location
4) if there is no location, locations ervice returns empty and user retries with a bigger radius until user gets results or there is no more results
Logging:
1) loggins usbsystem periodically scans services
2) For a scanned system logging picks logs and writes them to append only database
Location service is split into 2 dbs: long term db for storing location data like name, coordinates, reviews and in memory geo db to quickly answer range queries for get/nearBy from user phones. Gethash db is psted in in memory db like redis where key is coordinate and value is the location info.
1) For geohash db we user redis (or some in memory db) to quickly serve /get/neraby queries. Geohash is not big and can fit in a single in-memory instance.
2) For location reviews we can use SQL sharded by locationId or a nosql solution optimized for writes like cassandar. THe choice is not that important I believe as the number of reads and writes is equal. The only thing we have to do is to use pagination when returning results
3) For review updates we should use a nosql solution optimized for many concurrent writes and review counter can be quickly updates by many users.
4) User db is sharded by user Id to scale the db when the number of users grows
5) Log databse we use some append only db because it's the only type of operation the logging system does
Read-heavy paths:
1) Getoahsh and geohash databases are read heavy with prevalence of GET /v1/nearby requests. THe optimal way to scale it is to use nosql + shard by location id as said dbs are stateless
1) Failure in api gateway - another gateway picks the work because servers are satelesss
2) For reading locations we can use read replication where if one replica fails we can have a failover on a standby
3) Geohash info is quickly to rebuild and in case of geohash db fail we can tolerate some downtime (1-2) mins while db is being rebuilt
4) Failure to return any locations within readius can be solved by asking the user to increase the radius and retry the operation
5) user service or location service downtime can be fixed by picking a new replica on standby
6) FOr general subsystem failure we can use retry logic with exponential backoff strategy
1) Add ml solution to give recomendations for users about what to visit next
2) Add the functionality where you see what your friends also visited at any given time