List functional requirements for the system (Ask the chat bot for hints if stuck.)...
The users should be able to log in.
The users should be able to log out.
The users should be able to set goals.
The users should be able to monitor their progress.
The users should be able to view previous goals (history).
List non-functional requirements for the system...
The app should have 99.99 percent uptime.
The app should keep user privacy.
The app should have an average latency within 2 seconds.
Estimate the scale of the system you are going to design...
Assuming that the app will have 10 million users and 1 million of them will be active daily, each user may send average 2 requests each day, we will have an average of 2 million request per dasy which is 23 requests per second. But we must also consider in peak time there could be 100 requests per second, and our system should be able to handle that as well.
For the request info, we should record: userId, activity, timeStamp(start time and end time), colories burnt, heart rate, etc. Assuming we save the record in the format of json, each records maybe 10 kb. That means for each day we will have 20 gb new data per day. Assuming retention period is 5 years, that's 100 gb.
Define what APIs are expected from the system...
APIs:
login (username, password)
log out
LoadHistory (DateStart, DateEnd)
setgoals(userId, activityId, timeStamp)
finishGoals(activityId, startTime, endTime, userId, heart rate, calories)
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...
The database we choose to use should be SQL database such as MySQL. Because in this use case, latency is acceptable in 2 seconds, we don't need a fast read or write. Relational database is more consistent.
user: userId (primary Key), userName, email
activity: type(enum), calories, activityId (primary Key)
activity_records: userId(Foreign key), activityId(Foreign key),
start_timeStamp, end_timeStamp, calories_comsumed
goals: userId(Foreign key), activityId(Foreign Key), status
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...
Since the app is serving global users, we should be let the client connecting to CDN, and based on the geographic location, the clients should connect to the nearest data-center to reduce as much as latency as possible. We should have multiple datacenter which keeps replication of server and databases. The datacenter should have a load balancer that distribute requests to each server to make sure no single server is overloaded by the request. Each datacenter should have at least 3 copies of server and database that if one of them goes down, the other two can be promoted.
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...
The request will first go to CDN, find the nearest datacenter, then go to load balancer, and the request will be distributed to server. The server will do read and write from database.
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...
Because we are serving global users, and we have multiple database replications, we should have a master database that mainly responsible for writing data, and we generally read data from slave databases. The slave databases should copy the updates from master db with a job scheduler that do the updates every minute.
Explain any trade offs you have made and why you made certain tech choices...
The trade offs here is that I chose to not use in-memory cache and only relies on database. In-memory cache is fast but also expensive and hard to share among distributed servers. I assume that this app will not have use cases that users need frequently read/write data so we don't use in-memory cache.
Try to discuss as many failure scenarios/bottlenecks as possible.
If one server goes down, the DNS server should be configured to user round-robin with failover, and correctly direct the request to another healthy server.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?
To prevent DDOS attack, we can implement a rate-limiter that prevent malicious users sending requests too much and cause failures. The rate-limiter should be implement in server side and it should scale with server.