Lets start with what this fitness app will do. This application will keep track of two main forms of exercise, Endurance and Strength.
Database entity estimation:
Weightlifting data
Running data
HeartRate data
Goals data
Storage estimation
If lets say we have 1 million daily users, each of them posts 2 exercises per day, each of them set 1 goal per day (lets say 1 weight lifting, 1 endurance, both will also have HR data)
Traffic estimation
Cache estimation
We can use REST APIs to expose functionality of our service
We have already defined the data that we want to store, what kind of database should we be using? I would want to use a Document DB like MongoDB to keep the endurance data, strength data and goals data. This is because there are not a lot of relationships between the data entities in the database, furthermore I want to keep an array of speed data, which is of variable size, meaning the data that we keep is not structured. This is supported by the goals data, which stores different types of goals for different types of exercises. In addition, we need to do scaling as our user base grows, MongoDB is easy to scale horizontally.
To keep the route image, we will keep it in a cloud storage like Google Cloud or Azure. We will use a URL to access the image.
User Interface:
Servers
Database
From the traffic calculation, we see that there is going to be a lot of Location and HR requests per second, hence we must use multiple servers for each of them in order to meet the traffic demands. We will have a load balancer to divide the load to the different HR and Location servers. This is similar to the Normal Servers were we will also have multiple normal servers to meet the demands. Load balancers will be placed between the servers and the client for this.
In terms of how we can partition the data, one possible method could
be dividing the data by the UserID, There wont be a situation where there is a 'hot' user that can overload a server since a user can only exercise at most 3 times a day. Hence partitioning the data by userID seems like a viable option
Lastly, we can definitely have a cache for users who are more active on the application, who will access their past sessions more often. We can do this using a memcache and caching 20% of the data
We should also have a server that serves to clear expired data from the database and cloud storage. This allows the HR, Location and Normal Servers to continually meet demands without worrying about expired data in the database and cloud storage
Explain any trade offs you have made and why you made certain tech choices...
We want our locations and HR servers to be reliable, hence we should have multiple back up servers to continually meet high request demands
We should also have backup DBs to prevent loss of data. The server that serves to clear data can also serve to duplicate data
We could possibly have a function that allows users to follow other users on the application. This means users can view the past training sessions of other users. If this is the case, then we must rethink how we can partition the data. This is because there could be popular users whos training sessions are viewed by many people.
One possible way of dividing the data is through the ExerciseID or SessionID, Data with the same ExerciseID will be kept in the same DB, hence when people want to view the sessions of popular users, the request load is divided among the databases.