Coding Contest System Design
Never dive directly into the design phase; it may raise red flags during the interview!
Interviewer: Let’s talk about designing a coding contest platform similar to LeetCode contests or HackerRank contests
1. Feature Expectations [5 mins]
You: Before diving into the design, could you clarify a few points? Specifically, how many contests do we expect to run simultaneously? And do we anticipate handling live code submissions during contests?
Interviewer: That’s a good question. We aim to balance both aspects, with a strong emphasis on user-generated content and interactions. How would you approach managing user privacy and data security given the scale of the platform?
You: Great. For code evaluation, do we need to support multiple programming languages, and if so, how many? Also, should the evaluation be instant or can it be batched?
Interviewer: We need to support multiple languages—around 10 to start. The evaluation should be batched to handle large volumes of submissions efficiently, but we want to ensure results are available as quickly as possible.
You: Thanks for the details. This helps me better understand the requirements. I’ll proceed with the design considering these points.
Functional Requirements
- Register for Contests: Users should be able to sign up for available contests by selecting a contest, providing necessary information, and confirming their registration. This ensures users can participate in their chosen contests and are properly enrolled.
- Submit Code: Users should be able to upload their code solutions for contest problems. The code will be queued for evaluation, allowing participants to compete and showcase their skills.
- View Submissions: Users should be able to view their past code submissions and results. This helps participants review their work, analyze performance, and track progress throughout the contest.
- Generate Leaderboards: The system should create and display leaderboards showing user rankings based on contest performance. This motivates participants by highlighting top performers and fostering competition.
These features are key to how users interact with the coding contest platform and are the main focus of our design. For now, I won’t cover secondary features like detailed analytics or advanced user profiles. These are important but not our main focus right now.
It's important to understand the different types of users on the platform. We have participants who want to test their coding skills, educators creating challenges, and organizations looking for top talent. Each group has different needs, from easy code submissions to clear performance results.
By knowing who our users are whether they're coders, teachers, or recruiters, we can design the platform to better meet their needs and improve their experience.
Limit the number of features discussed to one or two, as covering more can be time-consuming and may detract from explaining the most critical aspects of the design.
2. Estimations [5 mins]
Understanding the data processing needs of a coding contest platform is crucial for ensuring adequate network and storage capacity, as well as planning for scalability as user demands increase. By anticipating these requirements, we can design a robust system that handles peak loads effectively, ensuring consistent performance and reliability as the platform grows.
- Assuming 1 contest every week with Daily Active Users (DAU) of 1 million users.
- On average, each user submits code 1-2 times per contest period, leading to a high volume of submissions.
- Assuming an average code submission size of 1 MB, the total daily storage requirement could be up to 2 TB if every user submits twice per day.
- For a high volume of submissions and result retrievals, peak bandwidth requirements may reach up to 10-20 Gbps to handle data transfers efficiently.
Clear estimations demonstrate planning and analytical skills crucial for system scalability and performance assessment.
3. Design Goals [5 mins]
Based on estimations and discussions, the non-functional requirements for the coding contest platform include ensuring high performance under heavy user loads, implementing robust data security measures, and designing scalable infrastructure to support rapid growth.
- Availability: The system must be operational and accessible at all times, especially during key contest periods. This involves ensuring high uptime with reliable infrastructure, redundancy, and failover mechanisms, and conducting regular monitoring to prevent and address issues.
- Scalability: The system should manage increasing users and submissions efficiently by scaling both vertically (upgrading resources) and horizontally (adding servers) to maintain performance during high demand.
- Low latency: The system must provide quick responses for actions like code submissions and result retrievals to ensure a smooth user experience, particularly during peak times.
- Security: The platform must protect user data and contest information with secure authentication, data encryption, and defenses against vulnerabilities like SQL injection and cross-site scripting (XSS).
Specify latency/throughput targets and decide on consistency/availability levels based of estimations discussed for robust system design.
4. High-Level Design [5-8 mins]
To design a high-level system architecture for Coding Contests, we'll focus on the following aspects:
I. APIs for Read/Write Scenarios
Defining APIs for a coding contest platform is important because it sets up clear communication between different parts of the system. This makes it easier to add new features or make changes in the future. APIs allow controlled access to the platform's functions, enabling smooth integration with other tools and services. This helps the platform grow and adapt, providing a well-organized and scalable environment for users, developers, and partners. By having well-defined APIs, the platform can manage user interactions efficiently and support continuous improvement and expansion.
Get Contests
Endpoint | Parameters | Response |
GET /contests |
{"contest": [...array of contests data...]} |
Register to Contest
Endpoint | Parameters | Response |
POST /register |
userId, contestId |
{"message": "User registered successfully for contest."} |
Get Contest Details
Endpoint | Parameters | Response |
GET /contest/{contestId} |
contestId |
contestId , name , date , rules , problems {problemId, title, description} |
Submit Code
Endpoint | Parameters | Response |
POST /submitcode |
userId , contestId , problemId , code , language |
submissionId , status , message |
Get Submission Results
Endpoint | Parameters | Response |
GET /result/{submissionId} |
submissionId |
submissionId , status , result |
Get Leadership Results
Endpoint | Parameters | Response |
GET /leaderboard/{contestId} |
contestId |
contestId , leaderboard {userId, username, score, rank} |
II. Database Schema
For a coding contest platform, NoSQL databases are used instead of traditional SQL databases because they handle large amounts of diverse data more easily. With many users interacting, submitting code, and generating results during contests, NoSQL databases like MongoDB or Cassandra can scale up to manage this data efficiently. They offer flexibility to handle different types of data and high traffic without being limited by fixed schemas. This makes the platform perform smoothly even during busy contest times, ensuring that data is stored and retrieved quickly and reliably.
Users Table
"userId": "UUID",
"username": "string",
"email": "string",
"passwordHash": "string",
"registrationDate": "timestamp"
}
Contests Table
"contestId": "UUID",
"name": "string",
"description": "string",
"startDate": "timestamp",
"endDate": "timestamp",
"status": "string",
}
Results Table
"resultId": "UUID",
"userId": "UUID",
"contestId": "UUID",
"problemId": "UUID",
"score": "number",
"runtime": "number",
"memoryUsage": "number",
"outcome": "string",
"submissionDate": "timestamp",
}
Ensure clear and concise communication of design choices and their implications to demonstrate deep understanding and critical thinking.
5. Deep Dive [10-12 mins]
Designing a system step by step helps us manage complex challenges by breaking them down into simpler, more manageable tasks. For a coding contest platform, this approach ensures that each component such as user management, contest handling, and result tracking is carefully planned and integrates seamlessly. It also allows for adjustments and improvements based on user feedback and evolving requirements, leading to a robust and effective final product that can handle large numbers of participants and interactions smoothly.1. Users
Users interact with the coding contest platform through various devices like desktops, laptops, and mobile phones. They can engage in several activities, including submitting code, viewing real-time leaderboards and registering for contests.
2. Load Balancer
Load balancer plays a crucial role in managing incoming traffic by distributing it across multiple servers. This distribution helps in maintaining high availability and reliability of the platform, preventing any single server from becoming a bottleneck and ensuring that user requests are handled efficiently even under high load.
3. API Gateway
API Gateway acts as the central entry point for all API requests to the platform. It is responsible for routing requests to the appropriate microservices based on the request type, handling authentication to ensure secure access, and managing authorization to enforce user permissions, thereby streamlining the request flow and enhancing security.
- /GET contests: Retrieves a list of all available contests. This endpoint provides details such as contest names, dates, and statuses, allowing users to view and browse through ongoing and upcoming contests.
- /POST register: Enables users to register for upcoming contests. The request includes user and contest details.
- /GET contest/{contestId}: Retrieves details about a specific contest, including contest rules, problem statements, and schedule.
- /POST submitcode: Allows users to submit their code for evaluation. The request includes the code and contest-related details.
- /GET result/{submissionId}: Retrieves the result of a specific code submission, including execution outcomes and performance metrics.
- /GET leaderboard/{contestId}: Retrieves the leaderboard for a specific contest, showing the rankings of participants based on their scores.
4. User Service
User Service manages all aspects related to users, including their registration, profile management, and authentication processes. It interacts with the User Database to handle user data such as credentials, profiles, and activity history, ensuring that user information is effectively managed and readily accessible.
5. User Database
User Database stores comprehensive data about users, including their profiles, login credentials, and historical activity. This database is integral for managing user-related information and ensuring that user details are consistently updated and available for various platform functionalities.
6. Contest Service
Contest Service oversees the management of contests, including their creation, registration, and rule enforcement. It interacts with the Contest Database to handle contest-related data, such as problems and participant details, ensuring that all aspects of contest management are efficiently executed.
7. Contest Database
Contest Database is responsible for storing all contest-related details, including problems, test cases, and participant data. It provides a centralized repository for contest information, allowing the Contest Service and other components to access and manage contest data effectively.
8. Code Evaluation Service
Code Evaluation Service processes code submissions by receiving them from users and preparing them for execution. It enqueues the submissions in the Message Queue for asynchronous processing, enabling efficient handling of code evaluation tasks.
9. Message Queue
Message Queue acts as a buffer for code submissions, ensuring reliable delivery to Worker Nodes for processing. It facilitates asynchronous processing by decoupling the receipt of code submissions from their evaluation, allowing the system to handle high volumes efficiently.
10. Worker Nodes
Worker Nodes are responsible for executing submitted code in isolated environments to ensure that any potential malicious activity is contained within a single container, preventing it from affecting others. They fetch relevant test cases from the Contest Database, run the code against these test cases, generate results, and store them in the Results Database. They also update user scores based on the execution outcomes.
11. Results Database
Results Database stores detailed results of code executions, including performance metrics such as runtime and memory usage, and outcomes of test cases. It provides a centralized location for storing and retrieving results, which are used for updating scores and leaderboards.
12. Leadership Service
Leadership Service manages and updates leaderboards for ongoing and past contests. It retrieves relevant data from the Contest Database to generate and maintain real-time rankings, ensuring that users have access to up-to-date leaderboard information.
13. Notification Service
The Notification Service sends push notifications to users' devices based on events such as new messages or updates in conversation status, enhancing user engagement by keeping users informed in real-time.
High Level Architecture of Coding Contest
6. Futher Optimizations [2 - 5 mins]
1. Caching
Caching in the coding contest platform architecture is essential for enhancing performance and user experience by storing frequently accessed data in fast memory. This approach reduces the load on primary databases and services, leading to quicker data retrieval and response times. Key caches include user cache, problem cache, and result cache, which streamline access to user profiles, contest problems, and submission results. This ensures efficient service delivery and scalability, especially during peak contest periods.
Data Stored in Cache
"key": "string",
"value": "string"
}
I. User Cache
The User Cache stores frequently accessed user data to reduce latency and improve performance. It enhances the efficiency of retrieving user information and interactions.
Example User Cache
{
"key": "cd91434e9a774973658a27e3b8601b62",
"value": {
"userId": "cd91434e9a774973658a27e3b8601b62",
"username": "codeguru",
"email": "codeguru@example.com",
"passwordHash": "54e3e334a14587f2ed63c9afef9cd05c",
"created_at": "2024-01-15 20:16:52"
}
},
{
...
},
]
II. Contest Cache
Caches frequently accessed video metadata and media URLs to reduce database load and improve response times for video retrieval requests.
Example Contest Cache
{
"key": "0cb95b4bf8be50faf0e462d6a2aca35e",
"value": {
"contestId": "0cb95b4bf8be50faf0e462d6a2aca35e",
"name": "Week 28 - Coding Contest",
"description": "Coding contest for the week 28 of year 2024,
"startDate": "2024-12-01 20:00:00,
"endDate": "2024-12-01 22:00:00",
"status": "active",
}
},
{
...
},
]
III. Results Cache
Caches recommendation data to quickly provide users with personalized content, reducing the need to repeatedly query the Recommendation Database.
Example Results Cache
{
"key": "2601b627ed01c03b21221670618eb9ca",
"value": {
"resultId": "2601b627ed01c03b21221670618eb9ca",
"userId": "cd91434e9a774973658a27e3b8601b62",
"contestId": "0cb95b4bf8be50faf0e462d6a2aca35e",
"problemId": "54e3e334a14587f2ed63c9afef9cd05c",
"score": 95.5,
"runtime": 49 ms,
"memoryUsage": 17.44 MB,
"outcome": "Accepted",
"submissionDate": 2024-12-01 22:17:00,
}
},
{
...
},
]
IV. Leadership Cache
Caches recommendation data to quickly provide users with personalized content, reducing the need to repeatedly query the Recommendation Database.
Example Leadership Cache
{
"key": "684e9771fd442c1bb6b1c05cf17d14c8",
"value": {
"contestId": "0cb95b4bf8be50faf0e462d6a2aca35e",
"leaderboard": [
{
"rank": 1,
"userId": "607db23177348b465e7801b890cdfc2a",
"username": "codelover"
"score": "99.8"
"lastSubmissionTime": 2024-12-01 22:13:57
},
{
...
}
]
}
},
{
...
},
]
2. CDN (Content Delivery Network)
Using a Content Delivery Network (CDN) in a coding contest platform can be beneficial, though it's not strictly required. Here are some reasons why a CDN might be useful:
I. Push CDN
A pull CDN fetches content from the main server when a user requests it for the first time. It then saves this content at various locations around the world, so future requests can be served faster. This is good for things that don't change often, like images, CSS, or JavaScript files. The CDN automatically updates when there are changes on the main server. For a coding contest platform, a pull CDN can handle problem statements, test cases, and other static content. It helps in delivering these items quickly and reduces the load on the main server.
II. Pull CDN
With a push CDN, content is manually uploaded to the CDN's servers before users request it. This way, the content is already available on the CDN's servers. Push CDN is useful for content that needs to be ready at a specific time, like new contest problems released at the start of a contest. For coding contests, a push CDN can ensure that new problem sets or important updates are available to all users right when the contest begins.
High Level Architecture of Coding Contest after Optimizations
7. Data Flow [5-8 mins]
It's essential to explain the end-to-end flow of the design, ensuring clarity on how data moves through the system. Based on estimations and discussions, the non-functional requirements for the system include addressing critical aspects such as performance under high user loads, robust data security measures, and scalable infrastructure to accommodate rapid growth.
User Participation:
- Registered users view available contests and select one to participate in.
- The request is sent to the API Gateway.
- The API Gateway routes the request to the Contest Service.
- Contest Service retrieves contest details and problem set from the Contests and Problems Databases.
- Contest details and problems are presented to the user.
Code Submission:
- The user submits their solution code for a problem in the contest.
- The request is sent to the API Gateway.
- The API Gateway routes the request to the Submission Service.
- Submission Service processes the code and stores it in the Submissions Database.
- The Submission Service may trigger a code evaluation process.
Leaderboard and Contest Closure:
- At the end of the contest, the platform calculates final standings.
- The request is sent to the API Gateway.
- The API Gateway routes the request to the Leaderboard Service.
- Leaderboard Service calculates rankings based on submission results and updates the Leaderboard Database.
- Users can view the final leaderboard and contest results through the platform interface.
Don't forget to explain the end to end flow of your design!
This architecture is designed to be scalable, resilient, and efficient, ensuring that the platform can handle a high volume of user interactions and data processing with minimal latency and high availability.