List functional requirements for the system (Ask the chat bot for hints if stuck.)...
the app needs to store activity history, user information, and leaderboard data
the app needs to work towards goals and
List non-functional requirements for the system...
highly available, be able to upload at any given time
eventual consistency is okay, your score not being on the leaderboard asap is probably fine
Estimate the scale of the system you are going to design...
user info:
name -> 10
age - > 2
weight -> 3 bytes per entry
activity -> 10 bytes per entry
goal -> 5 bytes
17 static bytes, about 15 per day for active
500 million users, 100 million are DAU
500 million * 17 = 8.5 GB
1.5 GB per day for entries
Define what APIs are expected from the system...
create_user(name,age,current_weight)
POST /api/v1/createUser
enter_activity(user_id,activity (running, biking etc.), distance, calories)
POST /api/v1/enterActivity
set_goal(user_id, goal, type (activity goal, calorie goal, weight goal))
POST /api/v1/{user}/setGoal
get_workout_history (user_id, filter (activity, calories burned, weight))
user_id can be used for rate limiting and throttling (Redis is great for that)
user_id can use OAuth or JWT to authenticate
timestamps can be added to each one to ensure that things are recorded properly
Defining the system data model early on will clarify how data will flow among different components of the system. Also you could draw an ER diagram using the diagramming tool to enhance your design...
User Info:
name, age, current_weight, user_id
A relational database is not necessary since we are not joining on anything. the user_id can be used to grab info from the timescale_db. NoSql might work better here for latency and scalability. MongoDB works fine here. We can store all the relevant info for the user (aka what you would see on the front page of the app). This would only include current metrics rather than historical data.
TimeScaleDB for workout logs - ideal for tracking weight and calories burned over time, great for metrics too since it has built in calculations like moving average, maximums etc. can connect to this via user_id.
For users who check more frequently or enter activity more frequently, we can use a cache to speed up their requests.
It could be smart to store all the data in one table, and simply filter out by activity for the ones we want. The only issue is that certain activities are measured by different attributes. running uses miles/km while swimming uses laps. This means if we store all the data in one table, well have a lot of empty columns. However, creating a separate table for each could be overly complex.
You should identify enough components that are needed to solve the actual problem from end to end. Also remember to draw a block diagram using the diagramming tool to augment your design. If you are unfamiliar with the tool, you can simply describe your design to the chat bot and ask it to generate a starter diagram for you to modify...
Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...
create user:
client => Load balancer => application server => store in MongoDB
enter activity =>
Dig deeper into 2-3 components and explain in detail how they work. For example, how well does each component scale? Any relevant algorithm or data structure you like to use for a component? Also you could draw a diagram using the diagramming tool to enhance your design...
microservice to continually update the leaderboard. It's okay if you latest run might deserve a leaderboard spot but you dont see it there for a bit. A separate microservice can hold the lowest points on the leaderboard, and update if any pushed value exceeds that point. This can occur every N hours.
microservice to track goals. this can be triggered on each push, checking if a goal was reached or to update a variable that indicates how far you were from said goal.
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?