How to Ace a System Design Interview
🎱 Follow my eight simple steps to ace a system design interview. 💫
The Eight Steps
Hey Pirates 🏴☠️
Today, I want to share my tips and tricks for acing system design interviews. System design interviews can be challenging to prepare for because, unlike algorithm questions, they don't rely on a few prescribed patterns. Instead, they require a vast amount of technical knowledge and experience. Moreover, they often come with deliberate ambiguity and the pressure of high-stakes interviews, which can be daunting for many candidates. However, fear not, as I will share a baseline template that can help you achieve at least a decent score in your interview. So let's dive into it.
Step 1. Identify Functional Requirements
Never start with a diagram. The initial step in a system design interview is to ask clarifying questions, which begins with understanding the functional requirements. For example, if given the task to "Design a Stories system where your shared photos disappear from your feed after a certain time," you can immediately identify three functional requirements: (1) a user uploads a photo, (2) the photo is shared with others, and (3) it disappears after a while. However, it's essential to tackle ambiguities and clarify additional requirements. For instance, who are we sharing the images with? Is it limited to the user's friends? What does "a certain time" mean? Is it 24 hours? Are we only considering images and not videos? Should we track views and likes? These clarifications are crucial for a comprehensive design.
Step 2. Identify Nonfunctional Requirements
Briefly discuss the five important aspects: consistency, availability, latency, scalability, and security. Most distributed systems today adopt either strong consistency or eventual consistency. Strong consistency provides up-to-date data but sacrifices latency and availability, making it suitable for applications like banking, payments, messaging systems, and massively multiplayer online games. On the other hand, eventual consistency offers low latency and high availability but may provide stale data in some cases. Examples include DNS, social media, and photo-sharing systems. High scalability is often essential for distributed systems that expect millions of users, and data encryption becomes necessary for handling sensitive information.
Step 3. Make Estimations
Ask the interviewer about the expected daily traffic. If the interviewer provides a specific number, try to calculate a reasonable estimation based on that. For example, if there are 10 million users per day, and each user views 10 stories on average, you can estimate that the system needs to handle around a thousand views per second. Here’s a pro tip. To simplify calculations, remember the number 86,400, which represents the number of seconds in a day. Round this number up to 100k or 10^5 to facilitate calculations.
Step 4. Define APIs
Identify the interfaces required for implementing the system and list them down. For example, in our case, we may need APIs such as addStory, uploadImage, getStories, and getFriends. Determine the parameters needed for each API, such as userId, storyId, timestamps, and status variables. Focus on the main requirements first and avoid incorporating non-essential features like views or like counts unless explicitly mentioned. Here’s another pro tip. Separate each API definition in a text box. This way, you can flexibly place the APIs while drawing the diagram.
Step 5. Define Databases
Determine the data models and specify the type of database to be used. For instance, MySQL or PostgreSQL for a relational database. For our design, I’ll choose a NoSQL database like MongoDB for scalability. Similar to the APIs, define the data model for each database in a text box. In our example, we'll need a StoryDatabase, FriendDatabase, and ImageStorage space. Establish the schema for each database, clearly defining the identifiers and partition keys. This is also an opportune moment to discuss indexing and sharding briefly. Explain the rationale behind your choice of partition keys, indexes, and shards.
Step 6. Draw the High-Level Architecture
It’s finally time to draw your system. Start by drawing a 3-tier diagram, dividing the canvas with three load balancers. This approach not only conveys the idea of workload balancing but also divides the canvas into four layers: client, frontend, backend, and database. Begin with the client layer, followed by the frontend and backend layers. While describing the flow, incorporate the previously defined APIs and database schema by moving the text boxes and placing them appropriately. You don’t need to draw another shape for each database. The use of separate text boxes for APIs and database schemas is sufficient while enhancing clarity and ease of understanding.
Step 7. Design the Components
In your interview, having a good understanding of the following four components should be sufficient: Backend Services, Message Queues, CRON Jobs, and caches. Backend services serve as the critical component, providing the main business logic by integrating necessary information from the database. In our example, the StoryFeedService fulfills this purpose. Message Queues facilitate the asynchronous processing of data and can be utilized to enqueue story requests in our Stories System. Examples of message queues include Redis and Kafka. CRON jobs refer to background workers that periodically execute tasks, and they can be responsible for dequeuing story requests, processing data, and storing it in databases. Lastly, caches act as lookup tables, enabling direct data retrieval without reading from the database. The two common types of caches are Most Frequently Used cache and Most Recently Used cache.
Step 8. Design Deep Dive
Delve into the details of your design and discuss the tradeoffs involved. Explain the reasons behind choosing a synchronous or asynchronous system and highlight the potential consequences of choosing otherwise. Reflect on the advantages and disadvantages of opting for eventual consistency over strong consistency. Discuss how you would handle failures in each system component and present fail-proof measures. For example, in our case, storing an uploadStory request in a message queue ensures data persistence even if the background worker fails. Replication strategies are worth considering to alleviate the workload on the database. A common technique is to replicate the original database across multiple machines and exclusively use the original for write operations. Periodically, the copies can synchronize with the original to ensure consistent data availability for read operations. Then sharding can be employed by grouping databases based on userId modulo 16, for example, to further distribute the workload.
Final Thoughts
The most critical takeaway for any system design interview is to avoid making assumptions. Showcase your comprehensive knowledge and demonstrate your skills to the fullest extent. I hope these eight steps provide you with a sense of how to prepare for and approach your system design interviews. If you found this video helpful, please like and subscribe. Feel free to share your thoughts in the comments below. Don't forget to visit my website for free coding-related resources and promotions, including a $1,000 discount on Springboard online bootcamps. See you in the next one. Bye.
Related
🎖️ Springboard: $1000 OFF ANY Online Tech Bootcamps!
⬆️ Pathrise: 1-to-1 Professional Career Mentorship
▶️ How to Ace Coding Interviews
▶️ How to Use LeetCode Effectively