Users should be able to view list of problems
Users should be able to view details of a problem
Users should be able to submit solution to a problem in a language of their choice
Users should be view leaderboard for competitions
Availability over consistency
System should be able to handle 100M+ DAU - Scalability
System should be able to submit answers and display results to users within 5 seconds - Low Latency
Security
100M DAU
Requests per day = ~ 100M * 5 = ~500M
Requests per second = ~500M/(24*60*60)
View List of problems API : GET /problems?pageId=1&limit=100
View problem API : GET /problems/:problemId
Submit solution API : POST /problems/:problemId/submit
View Leaderboard API : GET /leaderboard/:competitionId
Above APIs will serve requests for our functional requirements
Our core entities are : User, Problem, Submission
To store User information, we can use MySQL database as it is structured
To store Problem information, we can use MySQL database.
To store Submission information, we can use NoSQL data like Dynamo DB and Redis sorted set to fetch data for leaderboards
Our system serves the following request flows :
1) User wants to view a list of problems. In this case, client calls the API server(view list of problems API) which then calls the DB to fetch a list of problems.
2) User wants to view a problem : Client calls the API server(view problem API) which calls the DB to fetch information of a problem based on the problemId and returns to the user.
3) User wants to submit a solution : Client calls the API server(submit solution API) which sends this code to the AWS SQS which dynamically increases or reduces the number of containers required to run code based on the traffic, AWS SQS send this submitted solution to AWS Fargate container which has separate containers to run solutions in different languages. One container for Java, one for Python and so on. Then it sends the answer to the API server which persists it into the DB and sends it in response to the user.
4) User wants to view the leaderboard : Client calls the API server, which either fetches the leaderboard information from the Redis sorted set or the DB and returns it to the user.
1) User wants to view a list of problems. In this case, client calls the API server(view list of problems API) which then calls the DB to fetch a list of problems.
2) User wants to view a problem : Client calls the API server(view problem API) which calls the DB to fetch information of a problem based on the problemId and returns to the user.
3) User wants to submit a solution : Client calls the API server(submit solution API) which sends this code to the AWS SQS which dynamically increases or reduces the number of containers required to run code based on the traffic, AWS SQS send this submitted solution to AWS Fargate container which has separate containers to run solutions in different languages. One container for Java, one for Python and so on. Then it sends the answer to the API server which persists it into the DB and sends it in response to the user.
4) User wants to view the leaderboard : Client calls the API server, which either fetches the leaderboard information from the Redis sorted set or the DB and returns it to the user.
1) AWS Fargate - Security
How do we run the code submitted by the user ?
We can use a container like AWS Fargate which has separate containers for each language. Using this container instead of using API server, will safeguard our servers from crashing if user writes malicious code. Also using these containers will provide faster output with low latency as we can set CPU and resource limits for each user so that if user writes infinite loops or never ending programs, it will go beyond the CPU limits and kill the container. Also, it will help run the program in isolation and in a secure manner.
2) Redis sorted set for the Leaderboard - Low latency
How do we show leaderboard to users with low latency?
Showing a leaderboard to the user is not a simple task of fetching data from the database and sending it back to the user. This data needs fetching successful submissions from users and ordering them based on how accurate and fast they were submitted. This can be a time intensive task. But to address the requirement of low latency, we can use Redis sorted set which does all the aggregation and ordering needed for the leaderboard data.
We will use async data replication in order to serve requests with low latency over consistency.
We might have to do database sharding to decrease the load on our databases. And we will also need to do horizontal scaling of containers to prepare for an event of coding challenges where thousands of users will be submitting their code and containers will have to execute it all at once.
We need better sharding and scaling